package org.rubypeople.rdt.internal.codeassist; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.rubypeople.rdt.core.IMethod; import org.rubypeople.rdt.core.IOpenable; import org.rubypeople.rdt.core.IRubyElement; import org.rubypeople.rdt.core.IRubyModel; import org.rubypeople.rdt.core.IRubyProject; import org.rubypeople.rdt.core.IRubyScript; import org.rubypeople.rdt.core.ISourceRange; import org.rubypeople.rdt.core.IType; import org.rubypeople.rdt.core.RubyModelException; import org.rubypeople.rdt.core.compiler.CategorizedProblem; import org.rubypeople.rdt.internal.compiler.ISourceElementRequestor; import org.rubypeople.rdt.internal.compiler.ISourceElementRequestor.MethodInfo; public class ASTSourceRequestor implements ISourceElementRequestor { private Map<TypeInfo, List<MethodInfo>> types = new HashMap<TypeInfo, List<MethodInfo>>(); private Map<TypeInfo, List<String>> mixins = new HashMap<TypeInfo, List<String>>(); private List<TypeInfo> typeStack = new ArrayList<TypeInfo>(); private Map<String, TypeInfo> fullTypeNames = new HashMap<String, TypeInfo>(); private TypeInfo topLevel; private MethodInfo latestMethod; public ASTSourceRequestor() { topLevel = new TypeInfo(); topLevel.declarationStart = 0; topLevel.isModule = false; topLevel.name = "Object"; topLevel.nameSourceStart = 0; topLevel.nameSourceEnd = 0; topLevel.secondary = false; topLevel.superclass = null; } public void acceptConstructorReference(String name, int argCount, int offset) { } public void acceptFieldReference(String name, int offset) { } public void acceptImport(String value, int startOffset, int endOffset) { } public void acceptMethodReference(String name, int argCount, int offset) { } public void acceptMethodVisibilityChange(String methodName, int visibility) { } public void acceptMixin(String string) { TypeInfo info = getCurrentType(); List<String> duh = mixins.get(info); if (duh == null) { duh = new ArrayList<String>(); } duh.add(string); mixins.put(info, duh); } public void acceptModuleFunction(String function) { } public void acceptProblem(CategorizedProblem problem) { } public void acceptTypeReference(String name, int startOffset, int endOffset) { } public void acceptUnknownReference(String name, int startOffset, int endOffset) { } public void enterConstructor(MethodInfo constructor) { } public void enterField(FieldInfo field) { } public void enterMethod(MethodInfo method) { TypeInfo info = getCurrentType(); List<MethodInfo> methods = types.get(info); if (methods == null) methods = new ArrayList<MethodInfo>(); methods.add(method); types.put(info, methods); latestMethod = method; } public void acceptYield(String name) { latestMethod.blockVars = new String[] { name }; } private TypeInfo getCurrentType() { if (typeStack.isEmpty()) return topLevel; TypeInfo info = typeStack.get(typeStack.size() - 1); return info; } public void enterScript() { } public void enterType(TypeInfo type) { types.put(type, new ArrayList<MethodInfo>()); typeStack.add(type); mixins.put(type, new ArrayList<String>()); String fullName = getNamespace() + type.name; fullTypeNames.put(fullName, type); } private String getNamespace() { StringBuffer buffer = new StringBuffer(); List<TypeInfo> newTypeStack = new ArrayList<TypeInfo>(typeStack); newTypeStack.remove(newTypeStack.size() - 1); for (TypeInfo type : newTypeStack) { buffer.append(type.name); buffer.append("::"); } return buffer.toString(); } public void exitConstructor(int endOffset) { } public void exitField(int endOffset) { } public void exitMethod(int endOffset) { } public void exitScript(int endOffset) { } public void exitType(int endOffset) { typeStack.remove(typeStack.size() - 1); } public List<String> getMixins(String name) { for (String fullName : fullTypeNames.keySet()) { if (fullName.equals(name)) { TypeInfo info = fullTypeNames.get(fullName); return mixins.get(info); } } return Collections.emptyList(); } public Map<IMethod, String> getMethods(String mixin) { Map<IMethod, String> duh = new HashMap<IMethod, String>(); for (String fullName : fullTypeNames.keySet()) { if (fullName.equals(mixin)) { TypeInfo info = fullTypeNames.get(fullName); List<MethodInfo> methods = types.get(info); for (MethodInfo methodInfo : methods) { duh.put(new MethodInfoMethod(methodInfo), mixin); } return duh; } } return duh; } private static class MethodInfoMethod implements IMethod { private MethodInfo info; public MethodInfoMethod(MethodInfo info) { this.info = info; } public int getNumberOfParameters() throws RubyModelException { return info.parameterNames.length; } public String[] getParameterNames() throws RubyModelException { return info.parameterNames; } public int getVisibility() throws RubyModelException { return info.visibility; } public boolean isConstructor() { return info.isConstructor; } public boolean isPrivate() throws RubyModelException { return info.visibility == IMethod.PRIVATE; } public boolean isProtected() throws RubyModelException { return info.visibility == IMethod.PROTECTED; } public boolean isPublic() throws RubyModelException { return info.visibility == IMethod.PUBLIC; } public boolean isSingleton() { return info.isClassLevel; } public boolean exists() { return false; } public IRubyElement getAncestor(int ancestorType) { return null; } public IResource getCorrespondingResource() throws RubyModelException { return null; } public boolean isSimilar(IMethod method) { // TODO Auto-generated method stub return false; } public String getElementName() { return info.name; } public int getElementType() { return IRubyElement.METHOD; } public String getHandleIdentifier() { return null; } public IOpenable getOpenable() { return null; } public IRubyElement getParent() { return null; } public IPath getPath() { return null; } public IRubyElement getPrimaryElement() { return null; } public IResource getResource() { return null; } public IRubyModel getRubyModel() { return null; } public IRubyProject getRubyProject() { return null; } public IResource getUnderlyingResource() throws RubyModelException { return null; } public boolean isReadOnly() { return false; } public boolean isStructureKnown() throws RubyModelException { return false; } public boolean isType(int type) { return type == IRubyElement.METHOD; } public Object getAdapter(Class adapter) { return null; } public IType getDeclaringType() { return null; } public ISourceRange getNameRange() throws RubyModelException { return null; } public IRubyScript getRubyScript() { return null; } public IType getType(String name, int occurrenceCount) { return null; } public String getSource() throws RubyModelException { return null; } public ISourceRange getSourceRange() throws RubyModelException { return null; } public IRubyElement[] getChildren() throws RubyModelException { return null; } public boolean hasChildren() throws RubyModelException { return false; } public String[] getBlockParameters() throws RubyModelException { return info.blockVars; } } public void acceptBlock(int startOffset, int endOffset) { } }