blob: e8b9fbd314f2878fbe3ada2652022864d49d7219 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2017 xored software, Inc.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* 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<>();
/**
* @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<>();
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;
}
}