/* * Copyright (c) 2014 Google Inc. * * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse * Public License v1.0 which accompanies this distribution, and is available at * * http://www.eclipse.org/legal/epl-v10.html */ package com.google.eclipse.protobuf.ui.editor.hyperlinking; import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.IMPORT__PATH; import com.google.eclipse.protobuf.model.util.INodes; import com.google.eclipse.protobuf.model.util.Imports; import com.google.eclipse.protobuf.protobuf.Import; import com.google.inject.Inject; import com.google.inject.Provider; import org.eclipse.emf.ecore.EObject; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.hyperlink.IHyperlink; import org.eclipse.jface.text.hyperlink.IHyperlinkDetector; import org.eclipse.xtext.CrossReference; import org.eclipse.xtext.nodemodel.INode; import org.eclipse.xtext.resource.EObjectAtOffsetHelper; import org.eclipse.xtext.resource.XtextResource; import org.eclipse.xtext.ui.editor.hyperlinking.DefaultHyperlinkDetector; import org.eclipse.xtext.ui.editor.model.IXtextDocument; import org.eclipse.xtext.util.concurrent.IUnitOfWork; /** * Represents an implementation of interface <code>{@link IHyperlinkDetector}</code> to find and convert * {@link CrossReference elements}, at a given location, to {@code IHyperlink}. * * @author alruiz@google.com (Alex Ruiz) */ public class ProtobufHyperlinkDetector extends DefaultHyperlinkDetector { private static final IHyperlink[] NO_HYPERLINKS = null; @Inject private INodes nodes; @Inject private EObjectAtOffsetHelper eObjectAtOffsetHelper; @Inject private Imports imports; @Inject private Provider<ImportHyperlink> importHyperlinkProvider; @Override public IHyperlink[] detectHyperlinks(ITextViewer textViewer, final IRegion region, final boolean canShowMultipleHyperlinks) { IXtextDocument document = (IXtextDocument)textViewer.getDocument(); IHyperlink[] importHyperlinks = importHyperlinks(document, region); if (importHyperlinks != NO_HYPERLINKS) { return importHyperlinks; } return document.readOnly(new IUnitOfWork<IHyperlink[], XtextResource>() { @Override public IHyperlink[] exec(XtextResource resource) { return getHelper().createHyperlinksByOffset(resource, region.getOffset(), canShowMultipleHyperlinks); } }); } private IHyperlink[] importHyperlinks(final IXtextDocument document, final IRegion region) { return document.readOnly(new IUnitOfWork<IHyperlink[], XtextResource>() { @Override public IHyperlink[] exec(XtextResource resource) { EObject resolved = eObjectAtOffsetHelper.resolveElementAt(resource, region.getOffset()); if (resolved.eContainer() instanceof Import) { resolved = resolved.eContainer(); } if (!(resolved instanceof Import)) { return NO_HYPERLINKS; } Import anImport = (Import) resolved; if (!imports.isResolved(anImport)) { return NO_HYPERLINKS; } INode importUriNode = nodes.firstNodeForFeature(anImport, IMPORT__PATH); if (importUriNode.getLength() == 0) { return NO_HYPERLINKS; } ImportHyperlink hyperlink = importHyperlinkProvider.get(); hyperlink.update(imports.resolvedUriOf(anImport), importUriNode); return new IHyperlink[] { hyperlink }; } }); } }