blob: 0ae0986bbe7251b623ba4efb4a69ae84d7ebd8f3 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2008, 2018 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 n1, final @Nullable RAstNode n2) {
if (n1 != null) {
if (n2 != null) {
return n1.getStartOffset() - n2.getStartOffset();
}
else {
return -1;
}
}
else {
if (n2 != null) {
return 1;
}
else {
return 0;
}
}
}
@Override
public int compare(RElementAccess o1, RElementAccess o2) {
int offset= comparePosition(o1.getNameNode(), o2.getNameNode());
while (offset == 0) {
o1= o1.getNextSegment();
o2= o2.getNextSegment();
if (o1 != null) {
if (o2 != null) {
offset= comparePosition(o1.getNameNode(), o2.getNameNode());
}
else {
return 1;
}
}
else {
if (o2 != null) {
return -1;
}
else {
return 0;
}
}
}
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 IRFrame 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(boolean includeSlaves);
}