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; } }