blob: def982c1a5200f918489fcaa648f8f8f8bbff060 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2017 Red Hat Inc. and others.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Alexander Kurtakov - initial API and implementation
*******************************************************************************/
package org.eclipse.dltk.sh.internal.ui.text.hyperlink;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.hyperlink.AbstractHyperlinkDetector;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.texteditor.ITextEditor;
public class SourceHyperlinkDetector extends AbstractHyperlinkDetector {
private static final String SOURCE = "source";
@Override
public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion inputRegion,
boolean canShowMultipleHyperlinks) {
if ((inputRegion == null) || (textViewer == null)) {
return null;
}
try {
final IDocument doc = textViewer.getDocument();
final int lineNumber = doc.getLineOfOffset(inputRegion.getOffset());
final IRegion region = doc.getLineInformation(lineNumber);
final String line = doc.get(region.getOffset(), region.getLength());
if ((line != null) && (line.length() != 0)) {
final IHyperlink link = checkLine(region.getOffset(), line);
if (link != null) {
return new IHyperlink[] { link };
}
}
} catch (BadLocationException e) {
e.printStackTrace();
}
return null;
}
/**
* Checks if the specified line matches the <code>require</code> statement
*
* @param offset
* @param line
*/
private IHyperlink checkLine(int offset, final String line) {
int begin = 0;
int end = line.length();
while ((begin < end) && Character.isWhitespace(line.charAt(begin))) {
++begin;
}
while ((begin < end) && Character.isWhitespace(line.charAt(end - 1))) {
--end;
}
if (((begin + SOURCE.length()) < end) && line.startsWith(SOURCE, begin)) {
begin += SOURCE.length();
while ((begin < end) && Character.isWhitespace(line.charAt(begin))) {
++begin;
}
if (((begin + 2) < end) && (line.charAt(begin) == '(') && (line.charAt(end - 1) == ')')) {
++begin;
--end;
while ((begin < end) && Character.isWhitespace(line.charAt(begin))) {
++begin;
}
while ((begin < end) && Character.isWhitespace(line.charAt(end - 1))) {
--end;
}
}
return createLink(offset, line, begin, end);
}
return null;
}
/**
* Creates {@link IHyperlink} instance.
*
* This method is extracted to simplify testing.
*
* @param offset
* @param line
* @param begin
* @param end
* @return
*/
private IHyperlink createLink(int offset, final String line, int begin, int end) {
final ITextEditor editor = getAdapter(ITextEditor.class);
if (editor != null) {
final String requiredFile = line.substring(begin, end);
final Region region = new Region(offset + begin, end - begin);
IContainer container = ((FileEditorInput) getAdapter(ITextEditor.class).getEditorInput()).getFile()
.getParent();
IResource resourceToOpen = container.findMember(requiredFile);
if ((resourceToOpen != null) && (resourceToOpen.getType() == IResource.FILE)) {
return new IHyperlink() {
@Override
public void open() {
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
try {
IDE.openEditor(page, (IFile) resourceToOpen);
} catch (PartInitException e) {
}
}
@Override
public String getTypeLabel() {
return "Shell: source";
}
@Override
public String getHyperlinkText() {
return requiredFile;
}
@Override
public IRegion getHyperlinkRegion() {
return region;
}
};
}
}
return null;
}
}