package com.redhat.ceylon.eclipse.code.navigator; import static com.redhat.ceylon.eclipse.core.external.ExternalSourceArchiveManager.getExternalSourceArchiveManager; import static com.redhat.ceylon.eclipse.util.Nodes.getIdentifyingNode; import static com.redhat.ceylon.eclipse.util.Nodes.getReferencedNode; import java.util.Arrays; import java.util.Iterator; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jdt.core.IClassFile; import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.ISourceReference; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.ITypeRoot; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.internal.corext.util.JavaModelUtil; import org.eclipse.jdt.internal.corext.util.Messages; import org.eclipse.jdt.internal.ui.JavaPlugin; import org.eclipse.jdt.internal.ui.actions.ActionMessages; import org.eclipse.jdt.ui.JavaElementLabels; import org.eclipse.jdt.ui.JavaUI; import org.eclipse.jdt.ui.actions.OpenAction; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.util.OpenStrategy; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbenchSite; import org.eclipse.ui.PartInitException; import com.redhat.ceylon.compiler.typechecker.tree.Node; import com.redhat.ceylon.eclipse.code.editor.CeylonEditor; import com.redhat.ceylon.eclipse.code.editor.Navigation; import com.redhat.ceylon.eclipse.core.builder.CeylonBuilder; import com.redhat.ceylon.eclipse.core.external.CeylonArchiveFileStore; import com.redhat.ceylon.ide.common.model.BaseIdeModelLoader; import com.redhat.ceylon.ide.common.model.BaseIdeModule; import com.redhat.ceylon.ide.common.model.CeylonBinaryUnit; import com.redhat.ceylon.ide.common.model.IJavaModelAware; import com.redhat.ceylon.model.loader.ModelLoader.DeclarationType; import com.redhat.ceylon.model.typechecker.model.Declaration; import com.redhat.ceylon.model.typechecker.model.ModelUtil; public class CeylonOpenAction extends OpenAction { public CeylonOpenAction(IWorkbenchSite site) { super(site); } @Override public void selectionChanged(IStructuredSelection selection) { setEnabled(checkEnabled(selection)); } private boolean checkEnabled(IStructuredSelection selection) { if (selection.isEmpty()) return false; for (Iterator<?> iter= selection.iterator(); iter.hasNext();) { Object element= iter.next(); if (element instanceof ISourceReference) continue; if (element instanceof IFile) continue; if (JavaModelUtil.isOpenableStorage(element)) continue; if (element instanceof CeylonArchiveFileStore) continue; return false; } return true; } @Override public void run(IStructuredSelection selection) { if (!checkEnabled(selection)) return; run(selection.toArray()); } @Override public void run(Object[] elements) { if (elements == null) return; MultiStatus status= new MultiStatus(JavaUI.ID_PLUGIN, IStatus.OK, ActionMessages.OpenAction_multistatus_message, null); for (int i= 0; i < elements.length; i++) { Object element= elements[i]; try { Object elementToOpen= getElementToOpen(element); if (! (elementToOpen instanceof IPackageFragment)) { boolean activateOnOpen= OpenStrategy.activateOnOpen(); if (elementToOpen instanceof CeylonArchiveFileStore) { CeylonArchiveFileStore fileStore = (CeylonArchiveFileStore) elementToOpen; IFolder sourceArchiveFolder = getExternalSourceArchiveManager().getSourceArchive(fileStore.getArchivePath()); if (sourceArchiveFolder != null && sourceArchiveFolder.exists()) { IResource file = sourceArchiveFolder.findMember(fileStore.getEntryPath()); if (file instanceof IFile) { if (CeylonBuilder.isCeylon((IFile)file)) { elementToOpen = fileStore; } if (CeylonBuilder.isJava((IFile)file)){ //Open with the Class file object if available to have the full-featured ClassFileEditor. if (fileStore instanceof CeylonArchiveFileStore) { CeylonArchiveFileStore archiveFileStore = (CeylonArchiveFileStore) fileStore; IPath entryPath = archiveFileStore.getEntryPath(); String archivePath = archiveFileStore.getArchivePath().toOSString(); searchTheClassToDisplay: for (IProject project : CeylonBuilder.getProjects()) { for (BaseIdeModule module : CeylonBuilder.getProjectExternalModules(project)) { if (archivePath.equals(module.getSourceArchivePath())) { String className = ModelUtil.formatPath(Arrays.asList(entryPath.removeFileExtension().segments())); IType classToDisplay = JavaCore.create(project).findType(className); if (classToDisplay != null) { elementToOpen = classToDisplay; break searchTheClassToDisplay; } } } } } } } } } IEditorPart part= Navigation.openInEditor(elementToOpen, activateOnOpen); if (elementToOpen instanceof IJavaElement) { if (part instanceof CeylonEditor) { IJavaModelAware unit = CeylonBuilder.getUnit((IJavaElement)elementToOpen); if (unit instanceof CeylonBinaryUnit) { CeylonBinaryUnit<IProject,ITypeRoot,IJavaElement> ceylonUnit = (CeylonBinaryUnit<IProject,ITypeRoot,IJavaElement>) unit; CeylonEditor ceylonEditor = (CeylonEditor) part; IMember member = null; if (elementToOpen instanceof IClassFile) { member = ((IClassFile) elementToOpen).getType(); } if (elementToOpen instanceof IMember) { member = (IMember) elementToOpen; } if (member != null) { Declaration declaration = toCeylonDeclaration(member, ceylonUnit, ceylonUnit.getCeylonModule().getModuleManager().getModelLoader()); Node node = getReferencedNode(declaration, ceylonUnit.getCompilationUnit()); if (node != null) { Node identifyingNode = getIdentifyingNode(node); ceylonEditor.selectAndReveal(identifyingNode.getStartIndex(), identifyingNode.getDistance()); } } } } else if (part != null) { JavaUI.revealInEditor(part, (IJavaElement) elementToOpen); } } } } catch (PartInitException e) { String message= Messages.format(ActionMessages.OpenAction_error_problem_opening_editor, new String[] { JavaElementLabels.getTextLabel(element, JavaElementLabels.ALL_DEFAULT), e.getStatus().getMessage() }); status.add(new Status(IStatus.ERROR, JavaUI.ID_PLUGIN, IStatus.ERROR, message, null)); } catch (CoreException e) { String message= Messages.format(ActionMessages.OpenAction_error_problem_opening_editor, new String[] { JavaElementLabels.getTextLabel(element, JavaElementLabels.ALL_DEFAULT), e.getStatus().getMessage() }); status.add(new Status(IStatus.ERROR, JavaUI.ID_PLUGIN, IStatus.ERROR, message, null)); JavaPlugin.log(e); } } if (!status.isOK()) { IStatus[] children= status.getChildren(); ErrorDialog.openError(getShell(), ActionMessages.OpenAction_error_title, ActionMessages.OpenAction_error_message, children.length == 1 ? children[0] : status); } } private Declaration toCeylonDeclaration(IMember member, CeylonBinaryUnit ceylonUnit, BaseIdeModelLoader modelLoader) { if (member instanceof IType) { return modelLoader.convertToDeclaration(ceylonUnit.getCeylonModule(), ((IType) member).getFullyQualifiedName(), DeclarationType.VALUE); } if (member instanceof IMethod || member instanceof IField) { IType parent = member.getDeclaringType(); Declaration parentDeclaration = modelLoader.convertToDeclaration(ceylonUnit.getCeylonModule(), parent.getFullyQualifiedName(), DeclarationType.VALUE); if (parentDeclaration != null) { return parentDeclaration.getMemberOrParameter(ceylonUnit, member.getElementName(), null, false); } } return null; } }