/// <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 override IEnumerable <TypeDefinition> ResolveType() { IEnumerable <TypeDefinition> typeDefinitions; if (this.Name == "this" || (this.Name == "base" && this.ProgrammingLanguage == Language.CSharp) || (this.Name == "super" && this.ProgrammingLanguage == Language.Java)) { typeDefinitions = TypeDefinition.GetTypeForKeyword(this); } else { typeDefinitions = from declaration in FindMatches().OfType <VariableDeclaration>() where declaration.VariableType != null from definition in declaration.VariableType.ResolveType() select definition; } //TODO: figure out what the type should be when we have an indexer //if(Index != null) { //} return(typeDefinitions); }
/// <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> /// Finds matching <see cref="MethodDefinition">method definitions</see> for this method call. /// This method searches for matches in the ancestor scopes of the call. 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 <INamedEntity> FindMatches() { if (ParentStatement == null) { throw new InvalidOperationException("ParentStatement is null"); } if (IsConstructor || IsDestructor) { List <TypeDefinition> typeDefinitions; if (this.Name == "this" || (this.Name == "base" && this.ProgrammingLanguage == Language.CSharp) || (this.Name == "super" && this.ProgrammingLanguage == Language.Java)) { typeDefinitions = TypeDefinition.GetTypeForKeyword(this).ToList(); } else { var tempTypeUse = new TypeUse() { Name = this.Name, ParentStatement = this.ParentStatement, Location = this.Location }; typeDefinitions = tempTypeUse.ResolveType().ToList(); } //Handle case of C++ constructor initialization lists. //These will be marked as constructor calls. They can be used to initialize fields, though, in which case the call name will be the field name, //rather than a type name. if (!typeDefinitions.Any() && IsConstructorInitializer && ProgrammingLanguage == Language.CPlusPlus) { var containingType = ParentStatement.GetAncestorsAndSelf <TypeDefinition>().FirstOrDefault(); if (containingType != null) { //search this type and its parents for a field matching the name of the call var matchingField = containingType.GetParentTypesAndSelf(true).SelectMany(t => t.GetNamedChildren <VariableDeclaration>(this.Name)).FirstOrDefault(); if (matchingField != null) { typeDefinitions = matchingField.VariableType.ResolveType().ToList(); } } } var matchingMethods = from typeDefinition in typeDefinitions from method in typeDefinition.GetNamedChildren <MethodDefinition>(typeDefinition.Name) where SignatureMatches(typeDefinition.Name, method) select method; return(matchingMethods); } //If there's a calling expression, resolve and search under the results var callingScopes = GetCallingScope(); if (callingScopes != null) { IEnumerable <INamedEntity> matches = Enumerable.Empty <INamedEntity>(); foreach (var scope in callingScopes) { var localMatches = scope.GetNamedChildren <MethodDefinition>(this.Name).Where(SignatureMatches).ToList(); var callingType = scope as TypeDefinition; if (!localMatches.Any() && callingType != null) { //also search under the base types of the calling scope matches = matches.Concat(callingType.SearchParentTypes <MethodDefinition>(this.Name, SignatureMatches)); } else { matches = matches.Concat(localMatches); } } return(matches); } //search enclosing scopes and base types for the method foreach (var scope in ParentStatement.GetAncestors()) { var matches = scope.GetNamedChildren <MethodDefinition>(this).Where(SignatureMatches).ToList(); if (matches.Any()) { return(matches); } var typeDef = scope as TypeDefinition; if (typeDef != null) { //search the base types var baseTypeMatches = typeDef.SearchParentTypes <MethodDefinition>(this.Name, SignatureMatches).ToList(); if (baseTypeMatches.Any()) { return(baseTypeMatches); } } } //we didn't find it locally, search under imported namespaces return(from import in GetImports() from match in import.ImportedNamespace.GetDescendantsAndSelf <NameUse>().Last().FindMatches().OfType <NamedScope>() from child in match.GetNamedChildren <MethodDefinition>(this.Name) where SignatureMatches(child) select child); }
/// <summary> /// Finds definitions that match this name. /// </summary> /// <returns></returns> public virtual IEnumerable <INamedEntity> FindMatches() { if (ParentStatement == null) { throw new InvalidOperationException("ParentStatement is null"); } //handle keywords if (Name == "this" || (Name == "base" && ProgrammingLanguage == Language.CSharp) || (Name == "super" && ProgrammingLanguage == Language.Java)) { return(TypeDefinition.GetTypeForKeyword(this)); } //We don't want to match a NameUse to a MethodDefinition, so exclude them in all the queries //If there's a prefix, resolve that and search under results if (Prefix != null) { return(Prefix.FindMatches().SelectMany(ns => ns.GetNamedChildren <INamedEntity>(this.Name)).Where(e => !(e is MethodDefinition))); } //If there's a calling expression, match and search under results var callingScopes = GetCallingScope(); if (callingScopes != null) { IEnumerable <INamedEntity> matches = Enumerable.Empty <INamedEntity>(); foreach (var scope in callingScopes) { var localMatches = scope.GetNamedChildren(this.Name).Where(e => !(e is MethodDefinition)).ToList(); var callingType = scope as TypeDefinition; if (!localMatches.Any() && callingType != null) { //also search under the base types of the calling scope matches = matches.Concat(callingType.SearchParentTypes <INamedEntity>(this.Name, e => !(e is MethodDefinition))); } else { matches = matches.Concat(localMatches); } } return(matches); } //search enclosing scopes and base types foreach (var scope in ParentStatement.GetAncestors()) { var matches = scope.GetNamedChildren(this).Where(e => !(e is MethodDefinition)).ToList(); if (matches.Any()) { return(matches); } var expMatches = (from decl in scope.GetExpressions().SelectMany(e => e.GetDescendantsAndSelf <VariableDeclaration>()) where decl.Name == this.Name select decl).ToList(); if (expMatches.Any()) { return(expMatches); } var typeDef = scope as TypeDefinition; if (typeDef != null) { var baseTypeMatches = typeDef.SearchParentTypes <INamedEntity>(this.Name, e => !(e is MethodDefinition)).ToList(); if (baseTypeMatches.Any()) { return(baseTypeMatches); } } } //search if there is an alias for this name foreach (var alias in GetAliases()) { if (alias.AliasName == this.Name) { var targetName = alias.Target as NameUse; if (targetName == null) { //Target is not a NameUse, probably an Expression targetName = alias.Target.GetDescendantsAndSelf <NameUse>().LastOrDefault(); } if (targetName != null) { return(targetName.FindMatches()); } } } //we didn't find it locally, search under imported namespaces return(from import in GetImports() from match in import.ImportedNamespace.GetDescendantsAndSelf <NameUse>().Last().FindMatches().OfType <NamedScope>() from child in match.GetNamedChildren(this.Name) where !(child is MethodDefinition) select child); }