blob: 4103bd88da8de7349381e1cbaa0f888305da1f65 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2010, 2019 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.internal.r.ui.rhelp;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.jcommons.status.ProgressMonitor;
import org.eclipse.statet.jcommons.status.StatusException;
import org.eclipse.statet.jcommons.text.core.TextRegion;
import org.eclipse.statet.r.core.IRCoreAccess;
import org.eclipse.statet.r.core.RCore;
import org.eclipse.statet.r.core.model.IRFrame;
import org.eclipse.statet.r.core.model.IRFrameInSource;
import org.eclipse.statet.r.core.model.IRSourceUnit;
import org.eclipse.statet.r.core.model.RElementAccess;
import org.eclipse.statet.r.core.model.RElementName;
import org.eclipse.statet.r.core.model.RModel;
import org.eclipse.statet.r.core.rsource.ast.FCall;
import org.eclipse.statet.r.core.rsource.ast.NodeType;
import org.eclipse.statet.r.core.rsource.ast.RAstNode;
import org.eclipse.statet.rhelp.core.REnvHelp;
import org.eclipse.statet.rhelp.core.RHelpPage;
import org.eclipse.statet.rhelp.core.RHelpTopicLookup;
import org.eclipse.statet.rhelp.core.RPkgHelp;
import org.eclipse.statet.rj.renv.core.REnv;
@NonNullByDefault
public class RHelpLtkUI {
public static final String INFO_TARGET= "info"; //$NON-NLS-1$
public static REnvHelp getEnvHelp(final @Nullable IRSourceUnit sourceUnit)
throws StatusException {
final IRCoreAccess rCoreAccess= (sourceUnit != null) ?
sourceUnit.getRCoreAccess() : RCore.WORKBENCH_ACCESS;
REnv rEnv= rCoreAccess.getREnv();
if (rEnv == null) {
rEnv= RCore.WORKBENCH_ACCESS.getREnv();
}
return RCore.getRHelpManager().getHelpChecked(rEnv);
}
public static @Nullable Object searchTopicObject1(final REnvHelp help, final String topic,
final @Nullable RAstNode covering, final @Nullable IRSourceUnit sourceUnit)
throws CoreException {
if (covering != null) {
final IRFrameInSource frame= RModel.searchFrame(covering);
if (frame != null) {
final RHelpPage page= searchFrames(topic,
RModel.createDirectFrameList(frame), help );
if (page != null) {
return page;
}
}
}
if (sourceUnit != null) {
final RHelpPage page= searchFrames(topic,
RModel.createProjectFrameList(null, sourceUnit), help );
if (page != null) {
return page;
}
}
return null;
}
public static @Nullable Object searchTopicObject2(final REnvHelp help, final String topic,
final ProgressMonitor m) throws StatusException {
final List<RHelpPage> pages= help.getPagesForTopic(topic, m);
if (!pages.isEmpty()) {
if (pages.size() == 1) {
return pages.get(0);
}
return new RHelpTopicLookup(help.getREnv(), topic, ImCollections.toList(pages));
}
return null;
}
private static @Nullable RHelpPage searchFrames(final String topic,
final @Nullable List<IRFrame> frames, final REnvHelp help) {
if (frames == null) {
return null;
}
for (final IRFrame frame : frames) {
if (frame.getFrameType() == IRFrame.PACKAGE) {
final RPkgHelp pkgHelp= help.getPkgHelp(frame.getElementName().getSegmentName());
if (pkgHelp != null) {
final RHelpPage page= pkgHelp.getPageForTopic(topic);
if (page != null) {
return page;
}
}
}
}
return null;
}
public static @Nullable RElementName searchName(final @Nullable RAstNode node,
final TextRegion region, final boolean checkInterrupted) {
RElementAccess access= null;
for (RAstNode node0= node; node0 != null && access == null; node0= node0.getRParent() ) {
if (checkInterrupted && Thread.currentThread().isInterrupted()) {
return null;
}
final List<Object> attachments= node0.getAttachments();
for (final Object attachment : attachments) {
if (attachment instanceof RElementAccess) {
access= (RElementAccess)attachment;
final IRFrame frame= access.getFrame();
if ((frame != null && frame.getFrameType() != IRFrame.FUNCTION)
|| (RElementName.isPackageFacetScopeType(access.getType())) ) {
final RElementName e= getElementAccessOfRegion(access, region);
if (e != null) {
return e;
}
}
}
}
}
return null;
}
public static @Nullable RElementName searchNameOfFunction(final @Nullable RAstNode node,
final TextRegion region) {
for (RAstNode node0= node; node0 != null; node0= node0.getRParent() ) {
if (node0.getNodeType() == NodeType.F_CALL) {
final FCall fcall= (FCall) node0;
if (fcall.getArgsOpenOffset() != Integer.MIN_VALUE
&& fcall.getArgsOpenOffset() <= region.getStartOffset()) {
final List<Object> attachments= ((FCall) node0).getAttachments();
for (final Object attachment : attachments) {
if (attachment instanceof RElementAccess) {
final RElementAccess access= (RElementAccess) attachment;
final IRFrame frame= access.getFrame();
if (access.getNode() == fcall
&& frame != null && frame.getFrameType() != IRFrame.FUNCTION
&& access.getNextSegment() == null) {
final RElementName fName= RElementName.normalize(access);
if (RElementName.isRegularMainType(fName.getType())) {
return fName;
}
}
}
}
}
return null;
}
}
return null;
}
private static @Nullable RElementName getElementAccessOfRegion(final RElementAccess access,
final TextRegion region) {
if (access.getSegmentName() == null) {
return null;
}
int segmentCount= 0;
for (RElementAccess segment0= access; segment0 != null; segment0= segment0.getNextSegment()) {
segmentCount++;
final RAstNode nameNode= segment0.getNameNode();
if (nameNode != null
&& nameNode.getStartOffset() <= region.getStartOffset()
&& nameNode.getEndOffset() >= region.getEndOffset() ) {
if (RElementName.isRegularMainType(access.getType())) {
return access;
}
if (RElementName.isPackageFacetScopeType(access.getType())) {
if (segmentCount == 1) {
return access;
}
else /* (segmentCount > 1) */ {
if (RElementName.isRegularMainType(access.getNextSegment().getType())
&& access.getNextSegment().getSegmentName() != null) {
return RElementName.normalize(access);
}
}
}
return null;
}
}
return null;
}
private RHelpLtkUI() {}
}