/// <summary> /// Finds matching <see cref="IMethodDefinition">method definitions</see> from the /// <see cref="IScope.GetParentScopes()"/> of this usage. Because method calls can also be /// to constructors and destructors, this will also search for matching types and then /// constructors within those types /// </summary> /// <returns>An enumerable of method definitions that match this method call</returns> public override IEnumerable <IMethodDefinition> FindMatches() { IEnumerable <IMethodDefinition> matchingMethods = Enumerable.Empty <IMethodDefinition>(); if (IsConstructor || IsDestructor) { IEnumerable <ITypeDefinition> typeDefinitions; if (this.Name == "this" || (this.Name == "base" && this.ProgrammingLanguage == Language.CSharp)) { typeDefinitions = TypeDefinition.GetTypeForKeyword(this); } else { ITypeUse tempTypeUse = new TypeUse() { Name = this.Name, ParentScope = this.ParentScope, }; tempTypeUse.AddAliases(this.Aliases); typeDefinitions = tempTypeUse.FindMatches(); } matchingMethods = from typeDefinition in typeDefinitions from method in typeDefinition.GetChildScopesWithId <IMethodDefinition>(typeDefinition.Name) where Matches(method) select method; } else if (CallingObject != null) { matchingMethods = from matchingType in CallingObject.FindMatchingTypes() from typeDefinition in matchingType.GetParentTypesAndSelf() from method in typeDefinition.GetChildScopesWithId <IMethodDefinition>(this.Name) where Matches(method) select method; } else { var matches = base.FindMatches(); var matchingTypeMethods = from containingType in ParentScope.GetParentScopesAndSelf <ITypeDefinition>() from typeDefinition in containingType.GetParentTypes() from method in typeDefinition.GetChildScopesWithId <IMethodDefinition>(this.Name) where Matches(method) select method; matchingMethods = matches.Concat(matchingTypeMethods); } foreach (var method in matchingMethods) { yield return(method); } }
/// <summary> /// Finds all of the matching type definitions for all of the variable declarations that /// match this variable use /// </summary> /// <returns>An enumerable of matching type definitions</returns> public IEnumerable <ITypeDefinition> FindMatchingTypes() { IEnumerable <ITypeDefinition> typeDefinitions; if (this.Name == "this" || (this.Name == "base" && this.ProgrammingLanguage == Language.CSharp)) { typeDefinitions = TypeDefinition.GetTypeForKeyword(this); } else { var matchingVariables = FindMatches(); if (matchingVariables.Any()) { typeDefinitions = from declaration in matchingVariables where declaration.VariableType != null from definition in declaration.VariableType.FindMatches() select definition; } else { var tempTypeUse = new TypeUse() { Name = this.Name, ParentScope = this.ParentScope, ProgrammingLanguage = this.ProgrammingLanguage, }; if (CallingObject != null && CallingObject is IVariableUse) { var caller = CallingObject as IVariableUse; Stack <INamedScopeUse> callerStack = new Stack <INamedScopeUse>(); while (caller != null) { var scopeUse = new NamedScopeUse() { Name = caller.Name, ProgrammingLanguage = this.ProgrammingLanguage, }; callerStack.Push(scopeUse); caller = caller.CallingObject as IVariableUse; } INamedScopeUse prefix = null, last = null; foreach (var current in callerStack) { if (null == prefix) { prefix = current; last = prefix; } else { last.ChildScopeUse = current; last = current; } } prefix.ParentScope = this.ParentScope; tempTypeUse.Prefix = prefix; } tempTypeUse.AddAliases(this.Aliases); typeDefinitions = tempTypeUse.FindMatchingTypes(); } } return(typeDefinitions); }
/// <summary> /// Creates a type use element /// </summary> /// <param name="typeUseElement">the element to parse. Must be of a <see cref="ABB.SrcML.SRC.Type"/> or <see cref="ABB.SrcML.SRC.Name"/></param> /// <param name="context">the parser context</param> /// <returns>A Type Use object</returns> public virtual TypeUse ParseTypeUseElement(XElement typeUseElement, ParserContext context) { if(typeUseElement == null) throw new ArgumentNullException("typeUseElement"); XElement typeNameElement; // validate the type use typeUseElement (must be a SRC.Name or SRC.Type) if(typeUseElement.Name == SRC.Type) { typeNameElement = typeUseElement.Elements(SRC.Name).LastOrDefault(); } else if(typeUseElement.Name == SRC.Name) { typeNameElement = typeUseElement; } else { throw new ArgumentException("typeUseElement should be of type type or name", "typeUseElement"); } XElement lastNameElement = null; // this is the name element that identifies the type being used NamedScopeUse prefix = null; // This is the prefix (in A::B::C, this would be the chain A::B) XElement typeParameterArgumentList = null; // the argument list element holds the parameters for generic type uses var typeParameters = Enumerable.Empty<TypeUse>(); // enumerable for the actual generic parameters // get the last name element and the prefix if(typeNameElement != null) { lastNameElement = NameHelper.GetLastNameElement(typeNameElement); prefix = ParseNamedScopeUsePrefix(typeNameElement, context); } // if the last name element exists, then this *may* be a generic type use // go look for the argument list element if(lastNameElement != null) { if(prefix == null) { // if there is no prefix, then the argument list element will be the first sibling of lastNameElement typeParameterArgumentList = lastNameElement.ElementsAfterSelf(SRC.ArgumentList).FirstOrDefault(); } else { // otherwise, it will be the first *child* of lastNameElement typeParameterArgumentList = lastNameElement.Elements(SRC.ArgumentList).FirstOrDefault(); } } if(typeParameterArgumentList != null) { typeParameters = from argument in typeParameterArgumentList.Elements(SRC.Argument) where argument.Elements(SRC.Name).Any() select ParseTypeUseElement(argument.Element(SRC.Name), context); // if this is a generic type use and there is a prefix (A::B::C) then the last name element will actually be the first child of lastNameElement if(prefix != null) { lastNameElement = lastNameElement.Element(SRC.Name); } } // construct the type use var typeUse = new TypeUse() { Name = (lastNameElement != null ? lastNameElement.Value : string.Empty), ParentScope = context.CurrentScope, Location = context.CreateLocation(lastNameElement != null ? lastNameElement : typeUseElement), Prefix = prefix, ProgrammingLanguage = this.ParserLanguage, }; typeUse.AddTypeParameters(typeParameters); typeUse.AddAliases(context.Aliases); return typeUse; }