1 19 package org.netbeans.modules.ruby; 20 21 import java.util.List ; 22 23 import org.jruby.ast.ArgsCatNode; 24 import org.jruby.ast.ArgsNode; 25 import org.jruby.ast.ArgumentNode; 26 import org.jruby.ast.CallNode; 27 import org.jruby.ast.DefnNode; 28 import org.jruby.ast.DefsNode; 29 import org.jruby.ast.FCallNode; 30 import org.jruby.ast.ListNode; 31 import org.jruby.ast.LocalAsgnNode; 32 import org.jruby.ast.Node; 33 import org.jruby.ast.SplatNode; 34 import org.jruby.ast.VCallNode; 35 36 37 48 public final class Arity { 49 53 public static final Arity UNKNOWN = new Arity(-1, -1); 54 55 58 private int min; 59 60 64 private int max; 65 66 private Arity(int min, int max) { 67 this.min = min; 73 this.max = max; 74 } 75 76 public static Arity getCallArity(Node call) { 77 assert call instanceof CallNode || call instanceof VCallNode || call instanceof FCallNode; 78 79 Arity arity = new Arity(0, 0); 80 arity.initializeFromCall(call); 81 82 if (arity.min == -1) { 83 return UNKNOWN; 84 } else { 85 return arity; 86 } 87 } 88 89 public static boolean callHasArguments(Node call) { 90 assert call instanceof CallNode || call instanceof VCallNode || call instanceof FCallNode; 91 92 return getCallArity(call).min > 0; 93 } 94 95 @SuppressWarnings ("unchecked") 96 private void initializeFromCall(Node node) { 97 if (node instanceof FCallNode) { 98 Node argsNode = ((FCallNode)node).getArgsNode(); 99 100 initializeFromCall(argsNode); 101 } else if (node instanceof LocalAsgnNode) { 102 if (max < Integer.MAX_VALUE) { 103 max++; 104 } 105 } else if (node instanceof ArgsCatNode) { 106 ArgsCatNode args = (ArgsCatNode)node; 107 initializeFromCall(args.getFirstNode()); 108 max = Integer.MAX_VALUE; 112 } else if (node instanceof ArgsNode) { 113 ArgsNode args = (ArgsNode)node; 114 115 if (args != null) { 116 int value = args.getArity().getValue(); 117 118 if (value < 0) { 119 value = -(1 + value); 120 } 121 122 min = max = value; 123 } 124 } else if (node instanceof SplatNode) { 125 max = Integer.MAX_VALUE; 127 } else if (node instanceof CallNode) { 128 Node argsNode = ((CallNode)node).getArgsNode(); 129 initializeFromCall(argsNode); 130 } else if (node instanceof VCallNode) { 131 List <Node> children = node.childNodes(); 132 133 for (Node child : children) { 134 initializeFromCall(child); 135 } 136 } else if (node instanceof ListNode) { 137 List <Node> children = node.childNodes(); 138 139 for (Node child : children) { 140 if (child instanceof VCallNode) { 141 min++; 143 144 if (max < Integer.MAX_VALUE) { 145 max++; 146 } 147 } else { 148 initializeFromCall(child); 149 } 150 } 151 } else { 152 min++; 154 155 if (max < Integer.MAX_VALUE) { 156 max++; 157 } 158 } 159 } 160 161 @SuppressWarnings ("unchecked") 162 public static Arity getDefArity(Node method) { 163 assert method instanceof DefsNode || method instanceof DefnNode; 164 165 Arity arity = new Arity(0, 0); 166 167 List <Node> nodes = (List <Node>)method.childNodes(); 168 169 for (Node c : nodes) { 170 if (c instanceof ArgsNode) { 171 arity.initializeFromDef(c); 172 173 break; 174 } 175 } 176 177 if (arity.min == -1) { 178 return UNKNOWN; 179 } else { 180 return arity; 181 } 182 } 183 184 @SuppressWarnings ("unchecked") 185 private void initializeFromDef(Node node) { 186 if (node instanceof ArgsNode) { 187 ArgsNode argsNode = (ArgsNode)node; 188 189 if (argsNode.getArgs() != null) { 190 initializeFromDef(argsNode.getArgs()); 191 } 192 193 if (argsNode.getOptArgs() != null) { 194 initializeFromDef(argsNode.getOptArgs()); 195 } 196 197 if (argsNode.getRestArg() > 0) { 198 max = Integer.MAX_VALUE; 199 } 200 201 } else if (node instanceof ArgumentNode) { 204 min++; 205 max++; 206 } else if (node instanceof LocalAsgnNode) { 207 max++; 208 } else if (node instanceof ListNode) { 209 List <Node> children = node.childNodes(); 210 211 for (Node child : children) { 212 initializeFromDef(child); 213 } 214 } 215 } 216 217 226 public static boolean matches(Arity call, Arity method) { 227 if ((call == UNKNOWN) || (method == UNKNOWN)) { 231 return true; 232 } 233 234 if (call.min < method.min) { 235 return false; 236 } 237 238 if (call.max == Integer.MAX_VALUE) { 239 return true; 241 } 242 243 if (call.max > method.max) { 244 return false; 245 } 246 247 return true; 248 } 249 250 @Override 251 public String toString() { 252 return "Arity(" + min + ":" + ((max == Integer.MAX_VALUE) ? "unlimited" : max) + ")"; 253 } 254 255 public static Arity createTestArity(int min, int max) { 256 return new Arity(min, max); 257 } 258 } 259 | Popular Tags |