blob: 22690fd624e62ab6855f679e77c8b02d7271ff57 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2008, 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.r.core.model;
import java.util.Comparator;
import java.util.List;
import org.eclipse.statet.jcommons.collections.ImList;
import org.eclipse.statet.jcommons.lang.NonNull;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.r.core.rsource.ast.RAstNode;
/**
* Access of a variable of class in source code
*
* Is created by code analysis, not indent to implement by clients.
*/
@NonNullByDefault
public abstract class RElementAccess extends RElementName {
public static final Comparator<RElementAccess> NAME_POSITION_COMPARATOR=
new Comparator<RElementAccess>() {
private int comparePosition(final @Nullable RAstNode node1, final @Nullable RAstNode node2) {
if (node1 == node2) {
return 0;
}
if (node1 == null) {
return -1;
}
if (node2 == null) {
return 1;
}
return Integer.compare(node1.getStartOffset(), node2.getStartOffset());
}
@Override
public int compare(final RElementAccess o1, final RElementAccess o2) {
if (o1 == o2) {
return 0;
}
RElementAccess segment1= o1;
RElementAccess segment2= o2;
int offset;
while ((offset= comparePosition(segment1.getNameNode(), segment2.getNameNode())) == 0) {
segment1= o1.getNextSegment();
segment2= o2.getNextSegment();
if (segment1 == segment2) {
return 0;
}
if (segment1 == null) {
return -1;
}
if (segment2 == null) {
return 1;
}
}
return offset;
}
};
public static @Nullable RElementAccess getMainElementAccessOfNameNode(final RAstNode nameNode) {
RAstNode node= nameNode;
while (node != null) {
final List<Object> attachments= node.getAttachments();
for (final Object attachment : attachments) {
if (attachment instanceof RElementAccess) {
RElementAccess access= (RElementAccess)attachment;
do {
if (access.isMaster() && access.getNameNode() == nameNode) {
return (RElementAccess)attachment;
}
access= access.getNextSegment();
} while (access != null);
}
}
node= node.getRParent();
}
return null;
}
public static @Nullable RElementAccess getElementAccessOfNameNode(final RAstNode nameNode) {
RAstNode node= nameNode;
while (node != null) {
final List<Object> attachments= node.getAttachments();
for (final Object attachment : attachments) {
if (attachment instanceof RElementAccess) {
RElementAccess access= (RElementAccess)attachment;
do {
if (access.isMaster() && access.getNameNode() == nameNode) {
return access;
}
access= access.getNextSegment();
} while (access != null);
}
}
node= node.getRParent();
}
return null;
}
public abstract RFrame getFrame();
public abstract boolean isWriteAccess();
public abstract boolean isFunctionAccess();
public abstract boolean isCallAccess();
public boolean isMaster() {
return true;
}
public boolean isSlave() {
return false;
}
public RElementAccess getMaster() {
return this;
}
public abstract RAstNode getNode();
public abstract @Nullable RAstNode getNameNode();
@Override
public abstract @Nullable RElementAccess getNextSegment();
@Override
public RElementAccess getLastSegment() {
@NonNull RElementAccess lastSegment;
RElementAccess nextSegment= this;
do {
lastSegment= nextSegment;
} while ((nextSegment= nextSegment.getNextSegment()) != null);
return lastSegment;
}
public abstract ImList<? extends RElementAccess> getAllInUnit(final boolean includeSlaves);
}