/******************************************************************************* * Copyright (c) 2008, 2016 xored software, Inc. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * xored software, Inc. - initial API and Implementation (Alex Panchenko) *******************************************************************************/ package org.eclipse.dltk.ruby.testing.internal; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.Stack; import org.eclipse.dltk.ast.ASTNode; import org.eclipse.dltk.ast.ASTVisitor; import org.eclipse.dltk.ast.declarations.MethodDeclaration; import org.eclipse.dltk.ast.expressions.CallExpression; import org.eclipse.dltk.ast.expressions.StringLiteral; import org.eclipse.dltk.core.ISourceModule; import org.eclipse.dltk.core.search.indexing.IIndexConstants; import org.eclipse.dltk.ruby.ast.RubyCallArgument; import org.eclipse.dltk.ruby.ast.RubyClassDeclaration; import org.eclipse.dltk.ruby.core.RubyConstants; import org.eclipse.dltk.ruby.internal.parser.mixin.RubyMixinClass; import org.eclipse.dltk.ruby.internal.parser.mixin.RubyMixinModel; import org.eclipse.dltk.ruby.typeinference.RubyClassType; public class AbstractTestingEngineValidateVisitor extends ASTVisitor { private final Stack<ASTNode> stack = new Stack<ASTNode>(); /** * @param call * @param methods * @return */ protected boolean isMethodCall(CallExpression call, String[] methods) { if (call.getReceiver() != null) { return false; } final String methodName = call.getName(); for (int i = 0; i < methods.length; ++i) { if (methodName.equals(methods[i])) { return true; } } return false; } /** * @param nodeClass * @return */ protected boolean isNodeOnStack(Class<?> nodeClass) { for (int i = stack.size(); --i >= 0;) { if (nodeClass.isAssignableFrom(stack.get(i).getClass())) { return true; } } return false; } @Override public boolean visitGeneral(ASTNode node) throws Exception { stack.push(node); return super.visitGeneral(node); } @Override public void endvisitGeneral(ASTNode node) throws Exception { stack.pop(); super.endvisitGeneral(node); } protected boolean isMethodPrefix(final MethodDeclaration method, final String prefix) { final String methodName = method.getName(); return methodName.startsWith(prefix) && methodName.length() > prefix.length(); } protected boolean isSuperClassOf(ISourceModule module, RubyClassDeclaration declaration, final String className) { if (declaration.getSuperClassNames().contains(className)) return true; else { String classKey = className.replaceAll("::", //$NON-NLS-1$ String.valueOf(IIndexConstants.SEPARATOR)); Set<String> processedKeys = new HashSet<String>(); for (Iterator<String> iter = declaration.getSuperClassNames().iterator(); iter .hasNext();) { String superClass = iter.next(); RubyMixinModel model = RubyMixinModel.getInstance(module .getScriptProject()); RubyMixinClass mixinClass = model .createRubyClass(new RubyClassType(superClass .replaceAll("::", String //$NON-NLS-1$ .valueOf(IIndexConstants.SEPARATOR)))); if (mixinClass != null) // ssanders - Already know that it's indirect, because of // contains() above mixinClass = mixinClass.getSuperclass(); while (mixinClass != null) { if (processedKeys.add(mixinClass.getKey()) == true) { if (mixinClass.getKey().equals(classKey)) return true; mixinClass = mixinClass.getSuperclass(); } else { mixinClass = null; } } } } return false; } private boolean isRequire(CallExpression call) { return call.getReceiver() == null && RubyConstants.REQUIRE.equals(call.getName()) && call.getArgs().getChilds().size() == 1; } protected boolean isRequire(CallExpression call, String moduleName) { if (isRequire(call)) { final ASTNode argument = call.getArgs().getChilds().get(0); return isStringLiteralArgument(argument, moduleName); } return false; } protected boolean isStringLiteralArgument(ASTNode argument, String value) { if (argument instanceof RubyCallArgument) { RubyCallArgument callArg = (RubyCallArgument) argument; if (callArg.getValue() instanceof StringLiteral) { StringLiteral literal = (StringLiteral) callArg.getValue(); if (value.equals(literal.getValue())) { return true; } } } return false; } }