| /*=============================================================================# |
| # Copyright (c) 2008, 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.editors; |
| |
| import java.util.List; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| |
| import org.eclipse.statet.jcommons.collections.ImCollections; |
| import org.eclipse.statet.jcommons.collections.ImIdentityList; |
| import org.eclipse.statet.jcommons.text.core.TextRegion; |
| |
| import org.eclipse.statet.internal.r.ui.correction.RLinkedNamesAssistProposal; |
| import org.eclipse.statet.internal.r.ui.correction.RenameInRegionAssistProposal; |
| import org.eclipse.statet.internal.r.ui.correction.RenameInWorkspaceAssistProposal; |
| import org.eclipse.statet.ltk.core.LTKUtils; |
| import org.eclipse.statet.ltk.model.core.elements.ISourceStructElement; |
| import org.eclipse.statet.ltk.ui.sourceediting.assist.AssistInvocationContext; |
| import org.eclipse.statet.ltk.ui.sourceediting.assist.AssistProposalCollector; |
| import org.eclipse.statet.ltk.ui.sourceediting.assist.IQuickAssistComputer; |
| import org.eclipse.statet.r.core.model.IRCompositeSourceElement; |
| import org.eclipse.statet.r.core.model.IRLangSourceElement; |
| import org.eclipse.statet.r.core.model.IRSourceUnit; |
| import org.eclipse.statet.r.core.model.IRWorkspaceSourceUnit; |
| import org.eclipse.statet.r.core.model.RElementAccess; |
| import org.eclipse.statet.r.core.rsource.ast.NodeType; |
| import org.eclipse.statet.r.core.rsource.ast.RAstNode; |
| |
| |
| public class RQuickRefactoringComputer implements IQuickAssistComputer { |
| |
| |
| public RQuickRefactoringComputer() { |
| } |
| |
| |
| @Override |
| public IStatus computeAssistProposals(final AssistInvocationContext context, |
| final AssistProposalCollector proposals, final IProgressMonitor monitor) { |
| if (!(context.getAstSelection().getCovering() instanceof RAstNode)) { |
| return Status.OK_STATUS; |
| } |
| final RAstNode node = (RAstNode) context.getAstSelection().getCovering(); |
| |
| if (node.getNodeType() == NodeType.SYMBOL || node.getNodeType() == NodeType.STRING_CONST) { |
| RAstNode candidate = node; |
| SEARCH_ACCESS : while (candidate != null) { |
| final List<Object> attachments= candidate.getAttachments(); |
| for (final Object attachment : attachments) { |
| if (attachment instanceof RElementAccess) { |
| RElementAccess access= (RElementAccess) attachment; |
| SUB: while (access != null) { |
| if (access.getSegmentName() == null) { |
| break SUB; |
| } |
| if (access.getNameNode() == node) { |
| addAccessAssistProposals(context, access, proposals); |
| break SEARCH_ACCESS; |
| } |
| access = access.getNextSegment(); |
| } |
| } |
| } |
| candidate = candidate.getRParent(); |
| } |
| } |
| else if (context.getLength() > 0 && context.getSourceUnit() instanceof IRSourceUnit) { |
| proposals.add(new RenameInRegionAssistProposal(context)); |
| } |
| return Status.OK_STATUS; |
| } |
| |
| protected void addAccessAssistProposals(final AssistInvocationContext context, |
| final RElementAccess access, |
| final AssistProposalCollector proposals) { |
| final ImIdentityList<? extends RElementAccess> allAccess= ImCollections.toIdentityList( |
| access.getAllInUnit(false) ); |
| |
| proposals.add(new RLinkedNamesAssistProposal(RLinkedNamesAssistProposal.IN_FILE, context, access)); |
| |
| if (allAccess.size() > 2) { |
| TextRegion chunk= null; |
| { final ISourceStructElement sourceElement= context.getModelInfo().getSourceElement(); |
| if (sourceElement instanceof IRCompositeSourceElement) { |
| final List<? extends IRLangSourceElement> elements= ((IRCompositeSourceElement) sourceElement).getCompositeElements(); |
| final IRLangSourceElement element= LTKUtils.getCoveringSourceElement(elements, access.getNameNode().getStartOffset()); |
| if (element != null) { |
| chunk= element.getSourceRange(); |
| } |
| } |
| } |
| final int current= allAccess.indexOf(access); |
| if (current >= 0) { |
| if (current > 0 && current < allAccess.size() - 1) { |
| proposals.add(new RLinkedNamesAssistProposal(RLinkedNamesAssistProposal.IN_FILE_PRECEDING, context, access)); |
| proposals.add(new RLinkedNamesAssistProposal(RLinkedNamesAssistProposal.IN_FILE_FOLLOWING, context, access)); |
| } |
| if (chunk != null) { |
| int chunkBegin= 0; |
| for (final int offset= chunk.getStartOffset(); |
| chunkBegin < current; chunkBegin++) { |
| if (offset <= allAccess.get(chunkBegin).getNameNode().getStartOffset()) { |
| break; |
| } |
| } |
| int chunkEnd= current + 1; |
| for (final int offset= chunk.getEndOffset(); |
| chunkEnd < allAccess.size(); chunkEnd++) { |
| if (offset <= allAccess.get(chunkEnd).getNameNode().getStartOffset()) { |
| break; |
| } |
| } |
| if (chunkEnd - chunkBegin > 1) { |
| proposals.add(new RLinkedNamesAssistProposal(RLinkedNamesAssistProposal.IN_CHUNK, context, access, chunk)); |
| } |
| } |
| } |
| } |
| if (context.getSourceUnit() instanceof IRWorkspaceSourceUnit) { |
| proposals.add(new RenameInWorkspaceAssistProposal(context, access.getNameNode())); |
| } |
| } |
| |
| } |