blob: f59eb46114d861439bf97499c970824f32148d0d [file] [log] [blame]
package org.eclipse.dltk.ruby.internal.parser.visitors;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.dltk.ast.ASTNode;
import org.eclipse.dltk.ast.expressions.BooleanLiteral;
import org.eclipse.dltk.ast.expressions.CallArgumentsList;
import org.eclipse.dltk.ast.expressions.CallExpression;
import org.eclipse.dltk.ast.expressions.StringLiteral;
import org.eclipse.dltk.ruby.ast.RubyCallArgument;
import org.eclipse.dltk.ruby.ast.RubySymbolReference;
public class RubyAttributeHandler {
private static final String ATTR = "attr"; //$NON-NLS-1$
private static final String ATTR_ACCESSIBLE = "attr_accessible"; //$NON-NLS-1$
private static final String ATTR_ACCESSOR = "attr_accessor"; //$NON-NLS-1$
private static final String ATTR_INTERNAL = "attr_internal"; //$NON-NLS-1$
private static final String ATTR_INTERNAL_ACCESSOR = "attr_internal_accessor"; //$NON-NLS-1$
private static final String ATTR_INTERNAL_READER = "attr_internal_reader"; //$NON-NLS-1$
private static final String ATTR_INTERNAL_WRITER = "attr_internal_writer"; //$NON-NLS-1$
private static final String ATTR_PROTECTED = "attr_protected"; //$NON-NLS-1$
private static final String ATTR_READER = "attr_reader"; //$NON-NLS-1$
private static final String ATTR_READONLY = "attr_readonly"; //$NON-NLS-1$
private static final String ATTR_WRITER = "attr_writer"; //$NON-NLS-1$
private static final String CATTR_ACCESSOR = "cattr_accessor"; //$NON-NLS-1$
private static final String CATTR_READER = "cattr_reader"; //$NON-NLS-1$
private static final String CATTR_WRITER = "cattr_writer"; //$NON-NLS-1$
private static final String CLASS_INHERITABLE_ACCESSOR = "class_inheritable_accessor"; //$NON-NLS-1$
private static final String CLASS_INHERITABLE_ARRAY = "class_inheritable_array"; //$NON-NLS-1$
private static final String CLASS_INHERITABLE_ARRAY_WRITER = "class_inheritable_array_writer"; //$NON-NLS-1$
private static final String CLASS_INHERITABLE_HASH = "class_inheritable_hash"; //$NON-NLS-1$
private static final String CLASS_INHERITABLE_HASH_WRITER = "class_inheritable_hash_writer"; //$NON-NLS-1$
private static final String CLASS_INHERITABLE_READER = "class_inheritable_reader"; //$NON-NLS-1$
private static final String CLASS_INHERITABLE_WRITER = "class_inheritable_writer"; //$NON-NLS-1$
private static final Set<String> ATTRIBUTE_CREATION_NAMES = new HashSet<String>();
private static final Set<String> ATTRIBUTE_ACCESSOR_NAMES = new HashSet<String>();
private static final Set<String> ATTRIBUTE_READER_NAMES = new HashSet<String>();
private static final Set<String> ATTRIBUTE_WRITER_NAMES = new HashSet<String>();
private static final Set<String> META_ATTRIBUTE_CREATION_NAMES = new HashSet<String>();
static {
ATTRIBUTE_CREATION_NAMES.add(ATTR);
ATTRIBUTE_CREATION_NAMES.add(ATTR_ACCESSOR);
ATTRIBUTE_CREATION_NAMES.add(ATTR_ACCESSIBLE);
ATTRIBUTE_CREATION_NAMES.add(ATTR_INTERNAL);
ATTRIBUTE_CREATION_NAMES.add(ATTR_INTERNAL_ACCESSOR);
ATTRIBUTE_CREATION_NAMES.add(ATTR_INTERNAL_READER);
ATTRIBUTE_CREATION_NAMES.add(ATTR_INTERNAL_WRITER);
ATTRIBUTE_CREATION_NAMES.add(ATTR_PROTECTED);
ATTRIBUTE_CREATION_NAMES.add(ATTR_READER);
ATTRIBUTE_CREATION_NAMES.add(ATTR_READONLY);
ATTRIBUTE_CREATION_NAMES.add(ATTR_WRITER);
ATTRIBUTE_CREATION_NAMES.add(CATTR_ACCESSOR);
ATTRIBUTE_CREATION_NAMES.add(CATTR_READER);
ATTRIBUTE_CREATION_NAMES.add(CATTR_WRITER);
ATTRIBUTE_CREATION_NAMES.add(CLASS_INHERITABLE_ACCESSOR);
ATTRIBUTE_CREATION_NAMES.add(CLASS_INHERITABLE_ARRAY);
ATTRIBUTE_CREATION_NAMES.add(CLASS_INHERITABLE_ARRAY_WRITER);
ATTRIBUTE_CREATION_NAMES.add(CLASS_INHERITABLE_HASH);
ATTRIBUTE_CREATION_NAMES.add(CLASS_INHERITABLE_HASH_WRITER);
ATTRIBUTE_CREATION_NAMES.add(CLASS_INHERITABLE_READER);
ATTRIBUTE_CREATION_NAMES.add(CLASS_INHERITABLE_WRITER);
ATTRIBUTE_ACCESSOR_NAMES.add(ATTR_ACCESSOR);
ATTRIBUTE_ACCESSOR_NAMES.add(ATTR_ACCESSIBLE);
ATTRIBUTE_ACCESSOR_NAMES.add(ATTR_INTERNAL);
ATTRIBUTE_ACCESSOR_NAMES.add(ATTR_INTERNAL_ACCESSOR);
ATTRIBUTE_ACCESSOR_NAMES.add(CATTR_ACCESSOR);
ATTRIBUTE_ACCESSOR_NAMES.add(CLASS_INHERITABLE_ACCESSOR);
ATTRIBUTE_ACCESSOR_NAMES.add(CLASS_INHERITABLE_ARRAY);
ATTRIBUTE_ACCESSOR_NAMES.add(CLASS_INHERITABLE_HASH);
ATTRIBUTE_READER_NAMES.add(ATTR_INTERNAL_READER);
ATTRIBUTE_READER_NAMES.add(ATTR_PROTECTED);
ATTRIBUTE_READER_NAMES.add(ATTR_READER);
ATTRIBUTE_READER_NAMES.add(ATTR_READONLY);
ATTRIBUTE_READER_NAMES.add(CATTR_READER);
ATTRIBUTE_READER_NAMES.add(CLASS_INHERITABLE_READER);
ATTRIBUTE_WRITER_NAMES.add(ATTR_INTERNAL_WRITER);
ATTRIBUTE_WRITER_NAMES.add(ATTR_WRITER);
ATTRIBUTE_WRITER_NAMES.add(CATTR_WRITER);
ATTRIBUTE_WRITER_NAMES.add(CLASS_INHERITABLE_ARRAY_WRITER);
ATTRIBUTE_WRITER_NAMES.add(CLASS_INHERITABLE_HASH_WRITER);
ATTRIBUTE_WRITER_NAMES.add(CLASS_INHERITABLE_WRITER);
META_ATTRIBUTE_CREATION_NAMES.add(CATTR_ACCESSOR);
META_ATTRIBUTE_CREATION_NAMES.add(CATTR_READER);
META_ATTRIBUTE_CREATION_NAMES.add(CATTR_WRITER);
}
private final CallExpression call;
private List<ASTNode> readers;
private List<ASTNode> writers;
public RubyAttributeHandler(CallExpression call) {
super();
if (!isAttributeCreationCall(call)) {
throw new IllegalArgumentException();
}
this.call = call;
readers = new ArrayList<ASTNode>();
writers = new ArrayList<ASTNode>();
init();
}
private void init() {
String name = call.getName();
CallArgumentsList list = call.getArgs();
List<ASTNode> expr = list.getChilds();
Iterator<ASTNode> it = expr.iterator();
boolean create_reader = false;
boolean create_writer = false;
if (ATTRIBUTE_READER_NAMES.contains(name)) {
create_reader = true;
} else if (ATTRIBUTE_WRITER_NAMES.contains(name)) {
create_writer = true;
} else if (ATTRIBUTE_ACCESSOR_NAMES.contains(name)) {
create_reader = true;
create_writer = true;
} else if (name.equals(ATTR)) {
create_reader = true;
if (expr.size() > 0) {
ASTNode node = expr.get(expr.size() - 1);
if (node instanceof RubyCallArgument) {
node = ((RubyCallArgument) node).getValue();
}
if (node instanceof BooleanLiteral) {
BooleanLiteral lit = (BooleanLiteral) node;
create_writer = lit.boolValue();
}
}
}
while (it.hasNext()) {
ASTNode sr = it.next();
if (!(sr instanceof RubyCallArgument)) {
continue;
}
sr = ((RubyCallArgument) sr).getValue();
String attr = getText(sr);
if (attr == null) {
continue;
}
if (create_reader) {
readers.add(sr);
}
if (create_writer) {
writers.add(sr);
}
}
}
public List<ASTNode> getReaders() {
return readers;
}
public List<ASTNode> getWriters() {
return writers;
}
public static boolean isAttributeCreationCall(CallExpression c) {
if (c.getReceiver() != null)
return false;
String name = c.getName();
return ATTRIBUTE_CREATION_NAMES.contains(name);
}
public static boolean isMetaAttributeCreationCall(CallExpression c) {
if (c.getReceiver() != null)
return false;
String name = c.getName();
return META_ATTRIBUTE_CREATION_NAMES.contains(name);
}
public static String getText(ASTNode sr) {
if (sr == null)
return null;
String attr = null;
if (sr instanceof RubySymbolReference) {
attr = ((RubySymbolReference) sr).getName();
} else if (sr instanceof StringLiteral) {
attr = ((StringLiteral) sr).getValue();
}
return attr;
}
}