package com.redhat.ceylon.eclipse.code.open;
import static com.redhat.ceylon.eclipse.code.complete.CodeCompletions.getQualifiedDescriptionFor;
import static com.redhat.ceylon.eclipse.code.editor.Navigation.gotoDeclaration;
import static com.redhat.ceylon.eclipse.code.hover.DocumentationHover.getDocumentationFor;
import static com.redhat.ceylon.eclipse.code.hover.DocumentationHover.getLinkedModel;
import static com.redhat.ceylon.eclipse.code.html.HTMLPrinter.addPageEpilog;
import static com.redhat.ceylon.eclipse.code.html.HTMLPrinter.insertPageProlog;
import static com.redhat.ceylon.eclipse.code.outline.CeylonLabelProvider.getImageForDeclaration;
import static com.redhat.ceylon.eclipse.code.outline.CeylonLabelProvider.getModuleLabel;
import static com.redhat.ceylon.eclipse.code.outline.CeylonLabelProvider.getPackageLabel;
import static com.redhat.ceylon.eclipse.code.preferences.CeylonPreferenceInitializer.PARAMS_IN_DIALOGS;
import static com.redhat.ceylon.eclipse.code.preferences.CeylonPreferenceInitializer.PARAM_TYPES_IN_DIALOGS;
import static com.redhat.ceylon.eclipse.code.preferences.CeylonPreferenceInitializer.RETURN_TYPES_IN_DIALOGS;
import static com.redhat.ceylon.eclipse.code.preferences.CeylonPreferenceInitializer.TYPE_PARAMS_IN_DIALOGS;
import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.getCeylonProjects;
import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.getProjectTypeChecker;
import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.getProjects;
import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.getUnits;
import static com.redhat.ceylon.eclipse.java2ceylon.Java2CeylonProxies.hoverJ2C;
import static com.redhat.ceylon.eclipse.java2ceylon.Java2CeylonProxies.modelJ2C;
import static com.redhat.ceylon.eclipse.ui.CeylonPlugin.getOpenDialogFont;
import static com.redhat.ceylon.eclipse.ui.CeylonResources.CEYLON_MODULE;
import static com.redhat.ceylon.eclipse.ui.CeylonResources.CEYLON_PACKAGE;
import static com.redhat.ceylon.eclipse.ui.CeylonResources.CONFIG_LABELS;
import static com.redhat.ceylon.eclipse.util.EditorUtil.getCurrentEditor;
import static com.redhat.ceylon.eclipse.util.Highlights.PACKAGE_STYLER;
import static com.redhat.ceylon.eclipse.util.InteropUtils.toJavaString;
import static com.redhat.ceylon.model.cmr.JDKUtils.isJDKModule;
import static com.redhat.ceylon.model.cmr.JDKUtils.isOracleJDKModule;
import static com.redhat.ceylon.model.typechecker.model.ModelUtil.isNameMatching;
import static com.redhat.ceylon.model.typechecker.model.ModelUtil.isOverloadedVersion;
import static org.eclipse.jface.viewers.StyledString.COUNTER_STYLER;
import static org.eclipse.ui.dialogs.PreferencesUtil.createPreferenceDialogOn;
import java.io.File;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.ILabelDecorator;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IMemento;
import com.redhat.ceylon.compiler.typechecker.context.PhasedUnit;
import com.redhat.ceylon.eclipse.code.editor.CeylonEditor;
import com.redhat.ceylon.eclipse.code.html.HTML;
import com.redhat.ceylon.eclipse.code.preferences.CeylonFiltersPreferencePage;
import com.redhat.ceylon.eclipse.code.preferences.CeylonOpenDialogsPreferencePage;
import com.redhat.ceylon.eclipse.ui.CeylonPlugin;
import com.redhat.ceylon.eclipse.ui.CeylonResources;
import com.redhat.ceylon.eclipse.util.DocBrowser;
import com.redhat.ceylon.eclipse.util.Filters;
import com.redhat.ceylon.eclipse.util.ModelProxy;
import com.redhat.ceylon.ide.common.doc.DocGenerator;
import com.redhat.ceylon.ide.common.model.CeylonProject;
import com.redhat.ceylon.ide.common.model.CrossProjectSourceFile;
import com.redhat.ceylon.ide.common.model.EditedSourceFile;
import com.redhat.ceylon.ide.common.model.IResourceAware;
import com.redhat.ceylon.ide.common.model.IdeModule;
import com.redhat.ceylon.ide.common.model.JavaCompilationUnit;
import com.redhat.ceylon.ide.common.model.ProjectSourceFile;
import com.redhat.ceylon.model.typechecker.model.ClassOrInterface;
import com.redhat.ceylon.model.typechecker.model.Declaration;
import com.redhat.ceylon.model.typechecker.model.Module;
import com.redhat.ceylon.model.typechecker.model.Modules;
import com.redhat.ceylon.model.typechecker.model.Package;
import com.redhat.ceylon.model.typechecker.model.Referenceable;
import com.redhat.ceylon.model.typechecker.model.Unit;
public class OpenDeclarationDialog extends FilteredItemsSelectionDialog {
private static final String SHOW_SELECTION_MODULE =
"showSelectionModule";
private static final String SHOW_SELECTION_PACKAGE =
"showSelectionPackage";
private static final String EXCLUDE_DEPRECATED =
"excludeDeprecated";
private static final String EXCLUDE_JDK =
"excludeJDK";
private static final String EXCLUDE_ORA_JDK =
"excludeOracleJDK";
// private static final Image MEMBERS_IMAGE =
// CeylonPlugin.getInstance().getImageRegistry().get(CeylonResources.SHOW_MEMBERS);
private static final String SETTINGS_ID =
CeylonPlugin.PLUGIN_ID
+ ".openDeclarationDialog";
private boolean includeMembers;
private boolean excludeDeprecated;
private boolean excludeJDK;
private boolean excludeOracleJDK;
private int filterVersion = 0;
private boolean showSelectionPackage;
private boolean showSelectionModule;
private TogglePackageAction togglePackageAction;
private ToggleModuleAction toggleModuleAction;
private ToggleExcludeDeprecatedAction toggleExcludeDeprecatedAction;
private ToggleExcludeJDKAction toggleExcludeJDKAction;
private ToggleExcludeOracleJDKAction toggleExcludeOracleJDKAction;
// private ToolItem toggleMembersToolItem;
// private ToggleMembersAction toggleMembersAction;
protected String emptyDoc;
@Override
protected void applyFilter() {
includeMembers =
getPatternControl().getText()
.contains(".");
// toggleMembersAction.setChecked(includeMembers);
super.applyFilter();
}
// private final class ToggleMembersAction extends Action {
// private ToggleMembersAction() {
// super("Include Member Declarations", IAction.AS_CHECK_BOX);
// setImageDescriptor(CeylonPlugin.getInstance().getImageRegistry().getDescriptor(CeylonResources.SHOW_MEMBERS));
// }
//
// @Override
// public void run() {
// includeMembers=!includeMembers;
// applyFilter();
//// if (toggleMembersToolItem!=null) {
//// toggleMembersToolItem.setSelection(includeMembers);
//// }
// }
// }
private class ToggleExcludeDeprecatedAction
extends Action {
ToggleExcludeDeprecatedAction() {
super("Exclude Deprecated Declarations",
AS_CHECK_BOX);
}
@Override
public void run() {
excludeDeprecated=!excludeDeprecated;
filterVersion++;
applyFilter();
}
}
private class ToggleExcludeJDKAction
extends Action {
ToggleExcludeJDKAction() {
super("Exclude Java SDK",
AS_CHECK_BOX);
}
@Override
public void run() {
excludeJDK=!excludeJDK;
filterVersion++;
applyFilter();
}
}
private class ToggleExcludeOracleJDKAction
extends Action {
ToggleExcludeOracleJDKAction() {
super("Exclude Java SDK Internals",
AS_CHECK_BOX);
}
@Override
public void run() {
excludeOracleJDK=!excludeOracleJDK;
filterVersion++;
applyFilter();
}
}
private class TogglePackageAction
extends Action {
private TogglePackageAction() {
super("Show Selection Package",
AS_CHECK_BOX);
ImageDescriptor desc =
CeylonPlugin.imageRegistry()
.getDescriptor(CEYLON_PACKAGE);
setImageDescriptor(desc);
}
@Override
public void run() {
showSelectionPackage = !showSelectionPackage;
refresh();
}
}
private class ToggleModuleAction extends Action {
private ToggleModuleAction() {
super("Show Selection Module", AS_CHECK_BOX);
ImageDescriptor desc =
CeylonPlugin.imageRegistry()
.getDescriptor(CEYLON_MODULE);
setImageDescriptor(desc);
}
@Override
public void run() {
showSelectionModule = !showSelectionModule;
refresh();
}
}
protected void restoreDialog(IDialogSettings settings) {
super.restoreDialog(settings);
if (settings.get(SHOW_SELECTION_PACKAGE)!=null) {
showSelectionPackage =
settings.getBoolean(
SHOW_SELECTION_PACKAGE);
}
if (settings.get(SHOW_SELECTION_MODULE)!=null) {
showSelectionModule =
settings.getBoolean(
SHOW_SELECTION_MODULE);
}
if (settings.get(EXCLUDE_DEPRECATED)!=null) {
excludeDeprecated =
settings.getBoolean(EXCLUDE_DEPRECATED);
}
if (settings.get(EXCLUDE_JDK)!=null) {
excludeJDK =
settings.getBoolean(EXCLUDE_JDK);
}
if (settings.get(EXCLUDE_ORA_JDK)!=null) {
excludeOracleJDK =
settings.getBoolean(EXCLUDE_ORA_JDK);
}
else {
excludeOracleJDK = true;
}
if (togglePackageAction!=null) {
togglePackageAction.setChecked(
showSelectionPackage);
}
if (toggleModuleAction!=null) {
toggleModuleAction.setChecked(
showSelectionModule);
}
if (toggleExcludeDeprecatedAction!=null) {
toggleExcludeDeprecatedAction.setChecked(
excludeDeprecated);
}
if (toggleExcludeJDKAction!=null) {
toggleExcludeJDKAction.setChecked(
excludeJDK);
}
if (toggleExcludeOracleJDKAction!=null) {
toggleExcludeOracleJDKAction.setChecked(
excludeOracleJDK);
}
}
protected void storeDialog(IDialogSettings settings) {
super.storeDialog(settings);
settings.put(SHOW_SELECTION_MODULE,
showSelectionModule);
settings.put(SHOW_SELECTION_PACKAGE,
showSelectionPackage);
settings.put(EXCLUDE_DEPRECATED,
excludeDeprecated);
settings.put(EXCLUDE_JDK,
excludeJDK);
settings.put(EXCLUDE_ORA_JDK,
excludeOracleJDK);
}
private static Declaration toDeclaration(Object object) {
if (object instanceof DeclarationProxy) {
DeclarationProxy proxy =
(DeclarationProxy) object;
return proxy.get();
}
else {
return null;
}
}
public class Filter extends ItemsFilter {
boolean members = includeMembers;
boolean filterDeprecated = excludeDeprecated;
boolean filterJDK = excludeJDK;
boolean filterOracleJDK = excludeOracleJDK;
int version = filterVersion;
@Override
public boolean matchItem(Object item) {
Declaration declaration = toDeclaration(item);
Unit unit = declaration.getUnit();
Module module = unit.getPackage().getModule();
String moduleName = module.getNameAsString();
if (filterJDK &&
isJDKModule(moduleName) ||
filterOracleJDK &&
isOracleJDKModule(moduleName) ||
filterDeprecated &&
declaration.isDeprecated()) {
return false;
}
String pattern = getPattern();
int loc = pattern.indexOf('.');
if (loc<0) {
String name = declaration.getName();
if (name==null) {
return false;
}
else if (pattern.contains("*")) {
return isMatchingGlob(pattern, name);
}
else {
return isNameMatching(pattern, name);
}
}
else {
if (declaration.isClassOrInterfaceMember()) {
String typePattern =
pattern.substring(0,loc);
String memberPattern =
pattern.substring(loc+1);
Declaration type =
(Declaration)
declaration.getContainer();
return isNameMatching(memberPattern,
declaration) &&
isNameMatching(typePattern, type);
}
else {
return false;
}
}
}
@Override
public boolean isConsistentItem(Object item) {
return true;
}
private boolean isCompatibleFilter(
ItemsFilter itemsFilter) {
if (itemsFilter instanceof Filter) {
Filter filter = (Filter) itemsFilter;
return members==filter.members &&
version==filter.version;
}
else {
return false;
}
}
@Override
public boolean equalsFilter(ItemsFilter filter) {
return isCompatibleFilter(filter) &&
filter.getPattern()
.equals(getPattern());
}
@Override
public boolean isSubFilter(ItemsFilter filter) {
if (!isCompatibleFilter(filter)) {
return false;
}
else {
String pattern = getPattern();
String filterPattern = filter.getPattern();
int loc = pattern.indexOf('.');
int filterLoc = filterPattern.indexOf('.');
if (loc<0) {
return filterLoc<0 &&
filterPattern.startsWith(pattern);
}
else if (filterLoc>=0) {
String memberPattern =
pattern.substring(loc+1);
String typePattern =
pattern.substring(0,loc);
String filterMemberPattern =
filterPattern.substring(filterLoc+1);
String filterTypePattern =
filterPattern.substring(0,filterLoc);
return
filterMemberPattern
.startsWith(memberPattern) &&
filterTypePattern
.startsWith(typePattern);
}
else {
return false;
}
}
}
}
static abstract class BaseLabelProvider
implements IBaseLabelProvider {
@Override
public void removeListener(
ILabelProviderListener listener) {}
@Override
public boolean isLabelProperty(
Object element, String property) {
return false;
}
@Override
public void dispose() {}
@Override
public void addListener(
ILabelProviderListener listener) {}
}
class SelectionLabelDecorator
extends BaseLabelProvider
implements ILabelDecorator {
@Override
public String decorateText(String text, Object element) {
if (showSelectionPackage || showSelectionModule) {
Declaration dec =
toDeclaration(element);
if (dec!=null &&
!nameOccursMultipleTimes(dec)) {
try {
StringBuilder sb =
new StringBuilder(text);
if (showSelectionPackage) {
sb.append(" \u2014 ")
.append(getPackageLabel(dec));
}
if (showSelectionModule) {
sb.append(" \u2014 ")
.append(getModule(dec));
}
return sb.toString();
}
catch (Exception e) {
System.err.println(dec.getName());
e.printStackTrace();
}
}
}
return text;
}
@Override
public Image decorateImage(Image image,
Object element) {
return null;
}
}
static class DetailsLabelProvider
extends BaseLabelProvider
implements ILabelProvider {
@Override
public String getText(Object element) {
Declaration dec = toDeclaration(element);
if (dec!=null) {
try {
return getPackageLabel(dec);
/*+ " \u2014 " + getLocation(dwp)*/
}
catch (Exception e) {
System.err.println(dec.getName());
e.printStackTrace();
return "";
}
}
else if (element instanceof String) {
return (String) element;
}
else {
return "";
}
}
@Override
public Image getImage(Object element) {
Declaration dec = toDeclaration(element);
if (dec!=null) {
return CeylonResources.PACKAGE;
}
else {
return null;
}
}
}
static class MoreDetailsLabelProvider
extends BaseLabelProvider
implements ILabelProvider {
@Override
public String getText(Object element) {
Declaration dec = toDeclaration(element);
if (dec!=null) {
try {
return getModuleLabel(dec);
/* + " \u2014 " + getLocation(dwp)*/
}
catch (Exception e) {
System.err.println(dec.getName());
e.printStackTrace();
return "";
}
}
else if (element instanceof String) {
return (String) element;
}
else {
return "";
}
}
@Override
public Image getImage(Object element) {
Declaration dec = toDeclaration(element);
if (dec!=null) {
return CeylonResources.MODULE;
}
else {
return null;
}
}
}
static class EvenMoreDetailsLabelProvider
extends BaseLabelProvider
implements ILabelProvider {
@Override
public String getText(Object element) {
Declaration dec = toDeclaration(element);
if (dec!=null) {
try {
return getLocation(dec);
}
catch (Exception e) {
System.err.println(dec.getName());
e.printStackTrace();
return "";
}
}
else if (element instanceof String) {
return (String) element;
}
else {
return "";
}
}
@Override
public Image getImage(Object element) {
Declaration dec = toDeclaration(element);
if (dec!=null) {
return getLocationImage(dec);
}
else {
return null;
}
}
}
private StyledString label(Declaration dec) {
IPreferenceStore prefs = CeylonPlugin.getPreferences();
StyledString label =
getQualifiedDescriptionFor(dec,
prefs.getBoolean(TYPE_PARAMS_IN_DIALOGS),
prefs.getBoolean(PARAMS_IN_DIALOGS),
prefs.getBoolean(PARAM_TYPES_IN_DIALOGS),
prefs.getBoolean(RETURN_TYPES_IN_DIALOGS),
getPatternControl().getText(),
getOpenDialogFont());
if (nameOccursMultipleTimes(dec)) {
label.append(" \u2014 ", PACKAGE_STYLER)
.append(getPackageLabel(dec), PACKAGE_STYLER)
.append(" \u2014 ", COUNTER_STYLER)
.append(getModule(dec), COUNTER_STYLER);
}
return label;
}
class LabelProvider
extends StyledCellLabelProvider
implements IStyledLabelProvider,
ILabelProvider {
@Override
public boolean isLabelProperty(Object element,
String property) {
return false;
}
@Override
public Image getImage(Object element) {
Declaration dec = toDeclaration(element);
if (dec!=null) {
try {
return getImageForDeclaration(dec);
}
catch (Exception e) {
System.err.println(dec.getName());
e.printStackTrace();
return null;
}
}
else {
return null;
}
}
@Override
public String getText(Object element) {
return getStyledText(element).getString();
}
@Override
public StyledString getStyledText(Object element) {
Declaration dec = toDeclaration(element);
if (dec!=null) {
try {
return label(dec);
}
catch (Exception e) {
System.err.println(dec.getName());
e.printStackTrace();
return new StyledString(dec.getName());
}
}
else {
return new StyledString();
}
}
@Override
public void update(ViewerCell cell) {
Object element = cell.getElement();
if (element instanceof DeclarationProxy) {
StyledString styledText =
getStyledText(element);
cell.setText(styledText.toString());
cell.setStyleRanges(styledText.getStyleRanges());
cell.setImage(getImage(element));
}
else {
cell.setStyleRanges(new StyleRange[0]);
}
super.update(cell);
}
}
private class TypeSelectionHistory extends SelectionHistory {
protected DeclarationProxy restoreItemFromMemento(
IMemento element) {
String qualifiedName =
element.getString("qualifiedName");
String unitFileName =
element.getString("unitFileName");
String packageName =
element.getString("packageName");
String projectName =
element.getString("projectName");
if (projectName!=null) {
for (IProject project: getProjects()) {
if (project.getName()
.equals(projectName)) {
//search for a source file in the project
for (PhasedUnit phasedUnit:
getUnits(project)) {
String filename =
phasedUnit.getUnit()
.getFilename();
String pname =
phasedUnit.getPackage()
.getQualifiedNameString();
if (filename.equals(unitFileName) &&
pname.equals(packageName)) {
for (Declaration dec:
phasedUnit.getDeclarations()) {
try {
if (isPresentable(dec)) {
String qname =
dec.getQualifiedNameString();
if (qualifiedName.equals(qname)) {
return isFiltered(dec) ? null :
new DeclarationProxy(dec);
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
}
for (IProject project: getProjects()) {
//for archives, search all dependent modules
//this will find declarations in source archives
Modules modules =
getProjectTypeChecker(project)
.getContext()
.getModules();
for (Module module: modules.getListOfModules()) {
Package pkg =
module.getDirectPackage(packageName);
if (pkg!=null) {
for (Unit unit: pkg.getUnits()) {
if (unit.getFilename()
.equals(unitFileName)) {
for (Declaration dec:
unit.getDeclarations()) {
if (isPresentable(dec)) {
String qname =
dec.getQualifiedNameString();
if (qualifiedName.equals(qname)) {
return isFiltered(dec) ? null :
new DeclarationProxy(dec);
}
else if (qualifiedName.startsWith(qname+ '.')) {
for (Declaration mem: dec.getMembers()) {
if (isPresentable(mem)) {
String mqname =
mem.getQualifiedNameString();
if (qualifiedName.equals(mqname)) {
return isFiltered(dec) ? null :
new DeclarationProxy(mem);
}
}
}
}
}
}
}
}
}
}
}
return null;
}
protected void storeItemToMemento(Object item,
IMemento element) {
Declaration dec = toDeclaration(item);
Unit unit = dec.getUnit();
element.putString("qualifiedName",
dec.getQualifiedNameString());
element.putString("unitFileName",
unit.getFilename());
element.putString("packageName",
unit.getPackage()
.getQualifiedNameString());
if (unit instanceof EditedSourceFile ||
unit instanceof ProjectSourceFile ||
unit instanceof CrossProjectSourceFile ||
//TODO: is this correct:
unit instanceof JavaCompilationUnit) {
IResourceAware projectSourceFile =
(IResourceAware) unit;
IProject project = (IProject)
projectSourceFile.getResourceProject();
if (project!=null) {
element.putString("projectName",
project.getName());
}
}
}
}
public OpenDeclarationDialog(
boolean multi, boolean history,
Shell shell, String title,
String filterLabelText, String listLabelText) {
super(shell, multi, filterLabelText, listLabelText);
setTitle(title);
initLabelProviders(new LabelProvider(),
new SelectionLabelDecorator(),
new DetailsLabelProvider(),
new MoreDetailsLabelProvider(),
new EvenMoreDetailsLabelProvider());
if (history) {
setSelectionHistory(new TypeSelectionHistory());
}
}
@Override
protected IDialogSettings getDialogSettings() {
IDialogSettings settings =
CeylonPlugin.getInstance()
.getDialogSettings();
IDialogSettings section =
settings.getSection(SETTINGS_ID);
if (section == null) {
section = settings.addNewSection(SETTINGS_ID);
}
return section;
}
@Override
protected IStatus validateItem(Object item) {
return Status.OK_STATUS;
}
@Override
protected ItemsFilter createFilter() {
return new Filter();
}
@Override
protected Comparator<Object> getItemsComparator() {
return new Comparator<Object>() {
@Override
public int compare(Object x, Object y) {
return compareDeclarations(toDeclaration(x),
toDeclaration(y));
}
private int compareDeclarations(Declaration p,
Declaration q) {
int result = p.getName().compareTo(q.getName());
if (result!=0) {
return result;
}
else if (p.isClassOrInterfaceMember() &&
!q.isClassOrInterfaceMember()) {
return 1;
}
else if (!p.isClassOrInterfaceMember() &&
q.isClassOrInterfaceMember()) {
return -1;
}
else if (p.isClassOrInterfaceMember() &&
q.isClassOrInterfaceMember()) {
return compareDeclarations(
(Declaration) p.getContainer(),
(Declaration) q.getContainer());
}
else {
return 0;
}
}
};
}
Map<String,Integer> usedNames =
new HashMap<String,Integer>();
@Override
protected void fillContentProvider(
AbstractContentProvider contentProvider,
ItemsFilter itemsFilter,
IProgressMonitor monitor)
throws CoreException {
usedNames.clear();
monitor.beginTask("Filtering", estimateWork(monitor));
Set<String> searchedArchives = new HashSet<String>();
/*for (IProject project: getProjects()) {
TypeChecker typeChecker =
getProjectTypeChecker(project);
fillUnits(contentProvider, itemsFilter,
typeChecker.getPhasedUnits()
.getPhasedUnits(),
monitor);
if (monitor.isCanceled()) break;
Modules modules =
typeChecker.getContext()
.getModules();
for (Module module: modules.getListOfModules()) {
fillModule(module,
contentProvider, itemsFilter,
monitor, searchedArchives,
projectsToSearch);
if (monitor.isCanceled()) break;
}
}*/
for (@SuppressWarnings("rawtypes") CeylonProject project: getCeylonProjects()) {
@SuppressWarnings("rawtypes")
CeylonProject.Modules modules = project.getModules();
if (modules != null) {
for (Module module:
modules.getTypecheckerModules()
.getListOfModules()) {
fillModule(module,
contentProvider, itemsFilter,
monitor, searchedArchives);
if (monitor.isCanceled()) break;
}
}
}
monitor.done();
}
private void fillModule(Module mod,
AbstractContentProvider contentProvider,
ItemsFilter itemsFilter,
IProgressMonitor monitor,
Set<String> searchedArchives) {
if (includeModule(mod)) {
IdeModule module = (IdeModule) mod;
CeylonProject originalProject =
module.getOriginalProject();
if (originalProject == null
//|| !CeylonNature.isEnabled((IProject) originalProject.getIdeArtifact()) //unnecessary for now!
&& searchedArchives.add(uniqueIdentifier(mod))) {
fillModulePackages(module, contentProvider,
itemsFilter, monitor);
monitor.worked(1);
}
}
}
private void fillModulePackages(
IdeModule module,
AbstractContentProvider contentProvider,
ItemsFilter itemsFilter,
IProgressMonitor monitor) {
ArrayList<Package> copiedPackages =
new ArrayList<Package>(module.getPackages());
for (Package pack: copiedPackages) {
fillPackage(pack, module, contentProvider, itemsFilter);
monitor.worked(1);
if (monitor.isCanceled()) break;
}
}
private void fillPackage(Package pack, IdeModule module,
AbstractContentProvider contentProvider,
ItemsFilter itemsFilter) {
if (includePackage(pack, module)) {
for (Declaration dec: pack.getMembers()) {
fillDeclarationAndMembers(contentProvider,
itemsFilter, module, dec);
}
}
}
private boolean includePackage(Package pack, IdeModule module) {
boolean visibleFromProjectSource
= pack.isShared()
|| module.getIsProjectModule();
return visibleFromProjectSource
&& !filters.isFiltered(pack);
}
protected static class DeclarationProxy
extends ModelProxy {
private String location;
public DeclarationProxy(Declaration declaration) {
super(declaration);
location = getLocation(declaration);
}
@Override
public boolean equals(Object obj) {
if (this==obj) {
return true;
}
else if (obj instanceof DeclarationProxy) {
DeclarationProxy that =
(DeclarationProxy) obj;
if (super.equals(that)) {
return location==that.location ||
location!=null &&
that.location!=null &&
location.equals(that.location);
}
else {
return false;
}
}
else {
return false;
}
}
@Override
public int hashCode() {
return super.hashCode()
+ location.hashCode();
}
}
private void fillDeclarationAndMembers(
AbstractContentProvider contentProvider,
ItemsFilter itemsFilter,
IdeModule module, Declaration dec) {
if (includeDeclaration(module, dec) /*&&
//watch out for dupes!
(!module.getIsProjectModule() ||
!dec.getUnit()
.getFilename()
.endsWith(".ceylon"))*/) {
contentProvider.add(new DeclarationProxy(dec),
itemsFilter);
nameOccurs(dec);
if (includeMembers &&
dec instanceof ClassOrInterface) {
try {
ArrayList<Declaration> copiedMembers =
new ArrayList<Declaration>
(dec.getMembers());
for (Declaration member: copiedMembers) {
fillDeclarationAndMembers(
contentProvider,
itemsFilter,
module, member);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}
private void fillUnits(
AbstractContentProvider contentProvider,
ItemsFilter itemsFilter,
List<? extends PhasedUnit> units,
IProgressMonitor monitor) {
for (PhasedUnit unit: units) {
IdeModule jdtModule = (IdeModule)
unit.getPackage()
.getModule();
for (Declaration dec: unit.getDeclarations()) {
if (includeDeclaration(jdtModule, dec)) {
contentProvider.add(
new DeclarationProxy(dec),
itemsFilter);
nameOccurs(dec);
}
}
}
monitor.worked(1);
}
protected String getFilterListAsString(String preference) {
return CeylonPlugin.getPreferences()
.getString(preference);
}
private Filters filters = new Filters() {
@Override
protected String getFilterListAsString(String preference) {
return OpenDeclarationDialog.this
.getFilterListAsString(preference);
}
};
private boolean isFiltered(Declaration declaration) {
if (excludeDeprecated &&
declaration.isDeprecated()) {
return true;
}
return filters.isFiltered(declaration);
}
private boolean includeDeclaration(IdeModule module,
Declaration dec) {
try {
//only include declarations that could possibly
//be imported by the project source code
boolean visibleFromSourceModules;
if (dec.isToplevel()) {
visibleFromSourceModules =
module.getIsProjectModule()
|| dec.isShared();
}
else {
visibleFromSourceModules =
includeMembers
&& dec.isShared();
}
return visibleFromSourceModules
&& isPresentable(dec)
&& !isFiltered(dec);
}
catch (Exception e) {
e.printStackTrace();
return false;
}
}
private int estimateWork(IProgressMonitor monitor) {
int work = 0;
Set<String> searchedArchives =
new HashSet<String>();
for (IProject project: getProjects()) {
work++;
@SuppressWarnings("rawtypes")
CeylonProject ceylonProject =
modelJ2C().ceylonModel()
.getProject(project);
if (ceylonProject != null) {
@SuppressWarnings("rawtypes")
CeylonProject.Modules modules = ceylonProject.getModules();
if (modules != null) {
for (Module module:
modules.getTypecheckerModules()
.getListOfModules()) {
if (includeModule(module) &&
searchedArchives.add(uniqueIdentifier(module))) {
work += 1 + module.getPackages().size();
}
}
}
}
}
return work;
}
private boolean includeModule(Module module) {
return module instanceof IdeModule &&
!excluded(module) &&
!filters.isFiltered(module) &&
module.isAvailable();
}
private boolean excluded(Module module) {
String moduleName =
module.getNameAsString();
return
excludeJDK &&
isJDKModule(moduleName) ||
excludeOracleJDK &&
isOracleJDKModule(moduleName);
}
private static String uniqueIdentifier(Module m) {
String nameAndVersion =
m.getNameAsString() +
'#' + m.getVersion();
if (m instanceof IdeModule) {
@SuppressWarnings("rawtypes")
IdeModule module = (IdeModule) m;
final File artifact = module.getArtifact();
if (artifact==null) {
return nameAndVersion;
} else {
String archivePath = toJavaString(module.getSourceArchivePath());
if (archivePath == null) {
archivePath = artifact.getAbsolutePath();
}
return archivePath;
}
}
else {
return nameAndVersion;
}
}
private static String getModule(Declaration dec) {
Module module =
dec.getUnit()
.getPackage()
.getModule();
StringBuilder sb = new StringBuilder();
sb.append(module.getNameAsString());
if (module.getVersion()!=null) {
sb.append(" \"")
.append(module.getVersion())
.append("\"");
}
return sb.toString();
}
private static Image getLocationImage(Declaration dwp) {
Module module =
dwp.getUnit()
.getPackage()
.getModule();
if (module instanceof IdeModule) {
IdeModule m = (IdeModule) module;
if (m.getIsProjectModule()) {
// IProject project = dwp.getProject();
// if (project.isOpen()) {
return CeylonResources.FILE;
// }
// else {
// return CeylonResources.PROJECT;
// }
}
else {
return CeylonResources.REPO;
}
}
else {
return null;
}
}
private static String repositoryPath =
CeylonPlugin.getInstance()
.getCeylonRepository()
.getPath();
private static String getLocation(Declaration declaration) {
Unit unit = declaration.getUnit();
Module module = unit.getPackage().getModule();
if (module instanceof IdeModule) {
if (unit instanceof EditedSourceFile ||
unit instanceof ProjectSourceFile ||
unit instanceof CrossProjectSourceFile ||
//TODO: is this correct:
unit instanceof JavaCompilationUnit) {
IResourceAware sourceFile =
(IResourceAware) unit;
IFile ra = (IFile)
sourceFile.getResourceFile();
return ra==null ? null :
ra.getFullPath().toPortableString();
}
else {
IdeModule mod = (IdeModule) module;
String displayString =
mod.getRepositoryDisplayString();
if (repositoryPath.equals(displayString)) {
displayString = "IDE System Modules";
}
return displayString;
}
}
else {
return null;
}
}
private String toName(Declaration dec) {
String name = dec.getName();
if (dec.isClassOrInterfaceMember()) {
Declaration type =
(Declaration)
dec.getContainer();
name = type.getName() + "." + name;
}
return name;
}
private boolean nameOccursMultipleTimes(Declaration dec) {
Integer n = usedNames.get(toName(dec));
return n!=null && n>1;
}
private void nameOccurs(Declaration dec) {
String name = toName(dec);
Integer i = usedNames.get(name);
if (i==null) i=0;
usedNames.put(name, i+1);
}
static boolean isPresentable(Declaration d) {
return d.getName()!=null &&
!d.isAnonymous() &&
!isOverloadedVersion(d);
}
@Override
public String getElementName(Object item) {
return toDeclaration(item).getQualifiedNameString();
}
@Override
protected void fillViewMenu(IMenuManager menuManager) {
// toggleMembersAction = new ToggleMembersAction();
// toggleMembersAction.setChecked(includeMembers);
// menuManager.add(toggleMembersAction);
toggleExcludeDeprecatedAction =
new ToggleExcludeDeprecatedAction();
toggleExcludeDeprecatedAction.setChecked(
excludeDeprecated);
menuManager.add(toggleExcludeDeprecatedAction);
toggleExcludeJDKAction =
new ToggleExcludeJDKAction();
toggleExcludeJDKAction.setChecked(excludeJDK);
menuManager.add(toggleExcludeJDKAction);
toggleExcludeOracleJDKAction =
new ToggleExcludeOracleJDKAction();
toggleExcludeOracleJDKAction.setChecked(
excludeOracleJDK);
menuManager.add(toggleExcludeOracleJDKAction);
menuManager.add(new Separator());
super.fillViewMenu(menuManager);
togglePackageAction = new TogglePackageAction();
toggleModuleAction = new ToggleModuleAction();
menuManager.add(togglePackageAction);
menuManager.add(toggleModuleAction);
menuManager.add(new Separator());
Action configureAction =
new Action("Configure Filters and Labels...",
CeylonPlugin.imageRegistry()
.getDescriptor(CONFIG_LABELS)) {
@Override
public void run() {
createPreferenceDialogOn(getShell(),
CeylonOpenDialogsPreferencePage.ID,
new String[] {
CeylonOpenDialogsPreferencePage.ID,
CeylonPlugin.COLORS_AND_FONTS_PAGE_ID,
CeylonFiltersPreferencePage.ID
},
null).open();
filters.initFilters();
filterVersion++;
applyFilter();
}
};
menuManager.add(configureAction);
}
@Override
protected void refreshBrowserContent(DocBrowser browser,
Object[] selection) {
if (browser.isVisible()) {
try {
if (selection!=null &&
selection.length==1 &&
selection[0] instanceof DeclarationProxy) {
browser.setText(getDocumentationFor(null,
toDeclaration(selection[0]),
null));
}
else {
if (emptyDoc==null) {
StringBuilder buffer =
new StringBuilder();
insertPageProlog(buffer, 0,
HTML.getStyleSheet());
buffer.append("<i>Select a declaration to see its documentation here.</i>");
addPageEpilog(buffer);
emptyDoc = buffer.toString();
}
browser.setText(emptyDoc);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
public static boolean isMatchingGlob(
String filter, String name) {
if (name==null) {
return false;
}
int loc = 0;
boolean first = true;
for (String subfilter: filter.split("\\*")) {
int match = name.toLowerCase()
.indexOf(subfilter.toLowerCase(), loc);
if (match<0 || first && match>0) {
return false;
}
loc += match + subfilter.length();
first = false;
}
return true;
}
/*@Override
protected void createToolBar(ToolBar toolBar) {
super.createToolBar(toolBar);
toggleMembersToolItem = new ToolItem(toolBar, SWT.CHECK, 0);
toggleMembersToolItem.setImage(MEMBERS_IMAGE);
toggleMembersToolItem.setToolTipText("Show/Hide Members");
toggleMembersToolItem.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
includeMembers=!includeMembers;
applyFilter();
if (toggleMembersAction!=null) {
toggleMembersAction.setChecked(includeMembers);
}
}
});
}*/
// TODO this is a copy/paste of CeylonLocationListener.handleLink
@Override
void handleLink(String location, DocBrowser browser) {
Referenceable target = null;
CeylonEditor editor = null;
IEditorPart currentEditor = getCurrentEditor();
DocGenerator gen = hoverJ2C().getDocGenerator();
if (currentEditor instanceof CeylonEditor) {
editor = (CeylonEditor) currentEditor;
target = gen.getLinkedModel(
new ceylon.language.String(location),
editor.getParseController());
/*if (location.startsWith("ref:")) {
new FindReferencesAction(editor,
(Declaration) target).run();
close();
return;
}
else if (location.startsWith("sub:")) {
new FindSubtypesAction(editor,
(Declaration) target).run();
close();
return;
}
else if (location.startsWith("act:")) {
new FindRefinementsAction(editor,
(Declaration) target).run();
close();
return;
}
else if (location.startsWith("ass:")) {
new FindAssignmentsAction(editor,
(Declaration) target).run();
close();
return;
}*/
}
if (location.startsWith("doc:")) {
if (target==null) {
target = getLinkedModel(location);
}
if (target instanceof Declaration) {
String text =
getDocumentationFor(null,
(Declaration) target,
null);
if (text!=null) browser.setText(text);
}
if (target instanceof Package) {
String text =
getDocumentationFor(null,
(Package) target);
if (text!=null) browser.setText(text);
}
if (target instanceof Module) {
String text =
getDocumentationFor(null,
(Module) target);
if (text!=null) browser.setText(text);
}
}
if (location.startsWith("dec:")) {
if (target==null) {
target = getLinkedModel(location);
}
if (target!=null) {
gotoDeclaration(target);
close();
return;
}
}
}
@Override
public Declaration[] getResult() {
Object[] proxies = super.getResult();
if (proxies==null) {
return null;
}
else {
Declaration[] declarations =
new Declaration[proxies.length];
for (int i=0; i<proxies.length; i++) {
declarations[i] = toDeclaration(proxies[i]);
}
return declarations;
}
}
}