| /*=============================================================================# |
| # Copyright (c) 2014, 2020 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.search; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.core.runtime.SubMonitor; |
| import org.eclipse.jface.text.BadLocationException; |
| |
| import org.eclipse.statet.jcommons.text.core.TextLineInformation; |
| import org.eclipse.statet.jcommons.text.core.TextRegion; |
| |
| import org.eclipse.statet.ecommons.workbench.search.ui.LineElement; |
| |
| import org.eclipse.statet.ltk.core.SourceContent; |
| import org.eclipse.statet.ltk.model.core.element.SourceUnit; |
| import org.eclipse.statet.r.core.RProject; |
| import org.eclipse.statet.r.core.model.RElementAccess; |
| import org.eclipse.statet.r.core.model.RElementName; |
| import org.eclipse.statet.r.core.model.RFrame; |
| import org.eclipse.statet.r.core.model.RModel; |
| import org.eclipse.statet.r.core.model.RModelManager; |
| import org.eclipse.statet.r.core.model.RSourceFrame; |
| import org.eclipse.statet.r.core.model.RSourceUnit; |
| import org.eclipse.statet.r.core.model.RSourceUnitModelInfo; |
| import org.eclipse.statet.r.core.refactoring.RElementSearchProcessor; |
| import org.eclipse.statet.r.core.rsource.ast.RAsts; |
| import org.eclipse.statet.r.core.rsource.ast.RAstNode; |
| |
| |
| public class RElementSearch extends RElementSearchProcessor { |
| |
| |
| private final boolean searchWrite; |
| |
| RElementSearchResult result; |
| |
| private final StringBuilder sb= new StringBuilder(); |
| |
| |
| public RElementSearch(final RElementName name, |
| final RSourceUnit sourceUnit, final RElementAccess mainAccess, |
| final Mode mode, final boolean searchWrite) { |
| super(name, sourceUnit, mainAccess, mode, ALLOW_SUB_NAMEDPART); |
| |
| this.searchWrite= searchWrite; |
| } |
| |
| |
| public final boolean searchWrite() { |
| return this.searchWrite; |
| } |
| |
| @Override |
| protected void begin(final SubMonitor progress) { |
| super.begin(progress); |
| |
| this.result.removeAll(); |
| } |
| |
| @Override |
| protected void process(final RProject project, final List<SourceUnit> sus, |
| final SubMonitor progress) throws BadLocationException { |
| if (sus != null) { |
| int remaining= sus.size(); |
| for (final SourceUnit su : sus) { |
| progress.setWorkRemaining(remaining--); |
| |
| process((RSourceUnit)su, progress.newChild(1)); |
| } |
| } |
| } |
| |
| protected void process(final RSourceUnit sourceUnit, final SubMonitor progress) throws BadLocationException { |
| progress.setWorkRemaining(10); |
| sourceUnit.connect(progress.newChild(1)); |
| try { |
| RSourceUnit bestUnit= sourceUnit; |
| if (bestUnit.getUnderlyingUnit() != null && bestUnit.isSynchronized()) { |
| bestUnit= sourceUnit; |
| } |
| |
| final RSourceUnitModelInfo modelInfo= (RSourceUnitModelInfo)sourceUnit.getModelInfo(RModel.R_TYPE_ID, |
| RModelManager.MODEL_FILE, progress.newChild(1) ); |
| final SourceContent content= sourceUnit.getContent(progress.newChild(1)); |
| |
| final List<List<? extends RElementAccess>> allFrameAccess= new ArrayList<>(); |
| for (final String frameId : this.definitionFrameIds) { |
| final RFrame frame; |
| if (frameId == null) { |
| frame= modelInfo.getTopFrame(); |
| } |
| else { |
| frame= modelInfo.getReferencedFrames().get(frameId); |
| } |
| if (frame instanceof RSourceFrame) { |
| final List<? extends RElementAccess> allAccess= ((RSourceFrame)frame).getAllAccessOf( |
| this.mainName.getSegmentName(), true ); |
| if (allAccess != null && allAccess.size() > 0) { |
| allFrameAccess.add(allAccess); |
| } |
| } |
| } |
| |
| final String contentText= content.getText(); |
| final TextLineInformation lineInformation= content.getLines(); |
| final Map<Integer, LineElement<RSourceUnit>> lineElements= new HashMap<>(); |
| |
| for (final List<? extends RElementAccess> allAccess : allFrameAccess) { |
| for (RElementAccess access : allAccess) { |
| access= include(access); |
| if (access != null) { |
| final RAstNode nameNode= access.getNameNode(); |
| final TextRegion nameRegion= RAsts.getElementNameRegion(nameNode); |
| |
| final Integer lineNumber= Integer.valueOf( |
| lineInformation.getLineOfOffset(nameRegion.getStartOffset()) ); |
| LineElement<RSourceUnit> lineElement= lineElements.get(lineNumber); |
| if (lineElement == null) { |
| final int lineOffset= lineInformation.getStartOffset(lineNumber); |
| lineElement= new LineElement<>(bestUnit, lineNumber, lineOffset, |
| getContent(contentText, lineOffset, lineOffset + lineInformation.getLength(lineNumber)) ); |
| lineElements.put(lineNumber, lineElement); |
| } |
| |
| this.result.addMatch(new RElementMatch(lineElement, |
| nameRegion.getStartOffset(), nameRegion.getLength(), |
| (access.isWriteAccess() && access.getNextSegment() == null) )); |
| } |
| } |
| } |
| progress.setWorkRemaining(1); |
| } |
| finally { |
| sourceUnit.disconnect(progress.newChild(1)); |
| } |
| } |
| |
| private RElementAccess include(RElementAccess access) { |
| access= searchMatch(access); |
| return (access != null && access.isMaster() |
| && (!searchWrite() || access.isWriteAccess()) ) ? |
| access : null; |
| } |
| |
| private String getContent(final String text, final int start, final int end) { |
| this.sb.setLength(0); |
| for (int idx= start; idx < end; idx++) { |
| final char c= text.charAt(idx); |
| if (Character.isWhitespace(c) || Character.isISOControl(c)) { |
| this.sb.append(' '); |
| } else { |
| this.sb.append(c); |
| } |
| } |
| return this.sb.toString(); |
| } |
| |
| } |