| /*=============================================================================# |
| # 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() {} |
| |
| } |