blob: c2482eec92cd4e55397e6f9bca8dbdebde358965 [file] [log] [blame]
/*
* 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 };
}
});
}
}