internal static Dictionary<Tuple<string, string>, string> MakeDictionary(string connectionString) { using (var db = new SrcMLDataContext(connectionString)) { db.ObjectTrackingEnabled = false; db.CommandTimeout = 300; return MakeDictionary(db); } }
internal static Dictionary<Tuple<string, string>, string> MakeDictionary(SrcMLDataContext db) { var scopes = from scope in db.ValidScopes where scope.Definition.DefinitionTypeId == DefinitionType.DeclarationVariable let declaration = scope.Definition as VariableDeclaration select new KeyValuePair<Tuple<string, string>, string>(Tuple.Create(scope.XPath, declaration.DeclarationName), declaration.VariableTypeName); var scopeMap = scopes.ToDictionary(x => x.Key, x => x.Value); return scopeMap; }
private static bool Verify(SrcMLDataContext db, MethodDefinition def, XElement use) { var methodNameElement = SrcMLHelper.GetNameForMethod(use); bool namesMatch = def.MethodName == methodNameElement.Value; var numberOfArguments = use.Element(SRC.ArgumentList).Elements(SRC.Argument).Count(); var mininumNumberOfArguments = def.NumberOfMethodParameters - def.NumberOfMethodParametersWithDefaults; bool argCountMatches = numberOfArguments >= mininumNumberOfArguments && numberOfArguments <= def.NumberOfMethodParameters; return namesMatch && argCountMatches; }
internal static Dictionary<Tuple<string, string>, string> MakeLocalDictionary(SrcMLDataContext db, XElement fileUnit) { var pathToFileUnit = fileUnit.GetXPath(false); var scopes = from scope in db.ValidScopes where scope.Definition.DefinitionTypeId == DefinitionType.DeclarationVariable where scope.XPath.StartsWith(pathToFileUnit) let declaration = scope.Definition as VariableDeclaration select new KeyValuePair<Tuple<string, string>, string>( Tuple.Create(scope.XPath, declaration.DeclarationName), declaration.VariableTypeName ); var scopeMap = scopes.ToDictionary(x => x.Key, x => x.Value); return scopeMap; }
/// <summary> /// Initializes a new instance of the <see cref="CallGraph"/> class. /// </summary> /// <param name="xmlFileName">Name of the XML file.</param> /// <param name="db">The db.</param> public CallGraph(string xmlFileName, SrcMLDataContext db) { this._xmlFileName = xmlFileName; this._document = new SrcMLFile(xmlFileName); var methods = FetchMethods(db, xmlFileName); this.methodMap = new Dictionary<int, MethodDefinition>(); this.signatureMap = new Dictionary<string, int>(); foreach (var method in methods) { methodMap[method.Id] = method; signatureMap[method.MethodSignature] = method.Id; } this.edgeSet = new HashSet<Tuple<int, int>>(FetchEdgeSet(db, xmlFileName)); FetchCalleeLists(db); FetchCallerLists(db); }
/// <summary> /// Locates possible variable declarations that match the given name element. /// </summary> /// <param name="db">The db.</param> /// <param name="element">The element.</param> /// <param name="containerPath">The container path.</param> /// <returns>A collection of declarations that match this element</returns> public IEnumerable<VariableDeclaration> GetDeclarationForVariable(SrcMLDataContext db, XElement element, string containerPath) { if (null == db) throw new ArgumentNullException("db"); var declarations = from declaration in db.Definitions.OfType<VariableDeclaration>() where declaration.ArchiveId == this.Id where declaration.DeclarationName == element.Value where declaration.ValidScopes.Any(vs => vs.XPath == containerPath) select declaration; if (!declarations.Any()) { declarations = from declaration in db.Definitions.OfType<VariableDeclaration>() where declaration.Archive == this where declaration.DeclarationName == element.Value where declaration.IsGlobal ?? false select declaration; } return declarations; }
private static Dictionary<string, int> FetchMethodIdMap(SrcMLDataContext db, string xmlFileName) { var methods = from method in db.Definitions.OfType<MethodDefinition>() where method.Archive.Path == xmlFileName select new KeyValuePair<string, int>(method.XPath, method.Id); return methods.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); }
private static Dictionary<Tuple<XName, string, string, int>, List<int>> FetchMethodSignatureMap(SrcMLDataContext db, string xmlFileName) { Dictionary<Tuple<XName, string, string, int>, List<int>> methodMap = new Dictionary<Tuple<XName, string, string, int>, List<int>>(); var methods = from method in db.Definitions.OfType<MethodDefinition>() where method.Archive.Path == xmlFileName select new { Id = method.Id, ElementType = XName.Get(method.ElementXName), ClassName = method.MethodClassName, Name = method.MethodName, NumberOfParameters = method.NumberOfMethodParameters ?? 0, NumberOfParametersWithDefaults = method.NumberOfMethodParametersWithDefaults ?? 0, }; foreach (var m in methods) { for (int i = m.NumberOfParameters - m.NumberOfParametersWithDefaults; i <= m.NumberOfParameters; i++) { var key = MakeKey(m.ElementType, m.ClassName, m.Name, i); List<int> values; if (methodMap.TryGetValue(key, out values)) { values.Add(m.Id); } else { methodMap.Add(key, new List<int>() { m.Id }); } } } return methodMap; }
private void FetchCallerLists(SrcMLDataContext db) { var results = from method in db.Definitions.OfType<MethodDefinition>() where method.Archive.Path == _xmlFileName let callees = from call in method.CallsToMethod orderby call.LineNumber select Tuple.Create(call.LineNumber, call.CallerId, call.CalleeId) select new KeyValuePair<int, List<Tuple<int, int, int>>>(method.Id, callees.ToList()); callerMap = results.ToDictionary(kvp => kvp.Key, kvp => tuplesToMethodCalls(kvp.Value).ToList()); }
/// <summary> /// Builds the graph. /// </summary> /// <param name="connectionString">The connection string.</param> /// <param name="xmlFileName">the path to the SrcML document</param> internal static IEnumerable<MethodCall> BuildGraph(string connectionString, string xmlFileName) { Dictionary<Tuple<string, string>, string> scopeMap; Dictionary<string, int> idMap; Dictionary<Tuple<XName, string, string, int>, List<int>> signatureMap; SrcMLFile document; using (var db = new SrcMLDataContext(connectionString)) { db.ObjectTrackingEnabled = false; db.CommandTimeout = 300; var archive = (from a in db.Archives where a.Path == xmlFileName select a).FirstOrDefault(); if (null == archive) throw new SrcMLDataException("could not find archive " + xmlFileName); document = archive.Document; idMap = FetchMethodIdMap(db, xmlFileName); scopeMap = ValidScope.MakeDictionary(db); signatureMap = FetchMethodSignatureMap(db, xmlFileName); } foreach (var fileUnit in document.FileUnits) { foreach (var methodCall in BuildGraph(fileUnit, idMap, scopeMap, signatureMap)) { yield return methodCall; } } }
private static IEnumerable<Tuple<int, int>> FetchEdgeSet(SrcMLDataContext db, string xmlFileName) { var pairs = from call in db.MethodCalls where call.CallerDefinition.Archive.Path == xmlFileName select Tuple.Create(call.CallerId, call.CalleeId); return pairs; }
private static IEnumerable<MethodDefinition> FetchMethods(SrcMLDataContext db, string xmlFileName) { var methods = from method in db.Definitions.OfType<MethodDefinition>() where method.Archive.Path == xmlFileName select new { Id = method.Id, FileName = method.FileName, LineNumber = method.LineNumber, ElementXName = method.ElementXName, XPath = method.XPath, MethodClassName = method.MethodClassName, MethodName = method.MethodName, NumberOfMethodParameters = method.NumberOfMethodParameters, NumberOfMethodParametersWithDefaults = method.NumberOfMethodParametersWithDefaults, MethodSignature = method.MethodSignature }; foreach (var method in methods) { yield return new MethodDefinition() { Id = method.Id, FileName = method.FileName, LineNumber = method.LineNumber, ElementXName = method.ElementXName, XPath = method.XPath, MethodClassName = method.MethodClassName, MethodName = method.MethodName, NumberOfMethodParameters = method.NumberOfMethodParameters, NumberOfMethodParametersWithDefaults = method.NumberOfMethodParametersWithDefaults, MethodSignature = method.MethodSignature }; } }
/// <summary> /// Gets a collection of method definitions that match the given call element. /// </summary> /// <param name="db">The db.</param> /// <param name="call">The call.</param> /// <returns>A collection of method definitions that match</returns> public IEnumerable<MethodDefinition> GetMethodForCall(SrcMLDataContext db, XElement call) { if (null == db) throw new ArgumentNullException("db"); if (null == call) throw new ArgumentNullException("call"); SrcMLHelper.ThrowExceptionOnInvalidName(call, SRC.Call); var containingFunction = (from parent in call.Ancestors() where ContainerNames.MethodDefinitions.Any(n => n == parent.Name) select parent).First(); var className = SrcMLHelper.GetClassNameForMethod(containingFunction); TypeDefinition classDef = null; if (null != className) { var candidates = from ce in db.Definitions.OfType<TypeDefinition>() where ce.TypeName == className.Value select ce; if (candidates.Any()) { classDef = candidates.First(); } } var precedingElements = call.ElementsBeforeSelf(); if (precedingElements.Any()) { var last = precedingElements.Last(); var count = precedingElements.Count(); if (last.Name == OP.Operator && count > 1 && (last.Value == "." || last.Value == "->")) { var callingObject = precedingElements.Take(count - 1).Last(); if("this" != callingObject.Value) { var candidateDeclarations = this.GetDeclarationForVariable(db, callingObject); if (candidateDeclarations.Any()) { var declaration = candidateDeclarations.First(); var possibleTypes = from ce in db.Definitions.OfType<TypeDefinition>() where ce.TypeName == declaration.VariableTypeName select ce; if (possibleTypes.Any()) { classDef = possibleTypes.First(); } } } } } var numArguments = call.Element(SRC.ArgumentList).Elements(SRC.Argument).Count(); string typeName = null; if (null != classDef) typeName = classDef.TypeName; var methods = from method in db.Definitions.OfType<MethodDefinition>() where method.MethodName == call.Element(SRC.Name).Value where (typeName == null ? true : typeName == method.MethodClassName) let minNumberOfParameters = method.NumberOfMethodParameters - method.NumberOfMethodParametersWithDefaults where numArguments >= minNumberOfParameters && numArguments <= method.NumberOfMethodParameters select method; return methods; }
/// <summary> /// Locates possible variable declarations that match the given name element. /// </summary> /// <param name="db">The db.</param> /// <param name="element">The element.</param> /// <returns>A collection of declarations that match this element</returns> public IEnumerable<VariableDeclaration> GetDeclarationForVariable(SrcMLDataContext db, XElement element) { if (null == db) throw new ArgumentNullException("db"); if (null == element) throw new ArgumentNullException("element"); //SrcMLHelper.ThrowExceptionOnInvalidName(element, SRC.Name); var parentContainer = (from container in element.Ancestors() where ScopeContainers.Contains(container.Name) select container).FirstOrDefault(); if (null != parentContainer) { var parentXPath = parentContainer.GetXPath(false); return GetDeclarationForVariable(db, element, parentXPath); } return null; }
private static IEnumerable<MethodDefinition> FindMethodsInArchive(SrcMLDataContext db, Archive archive, XElement element) { return archive.GetMethodForCall(db, element); }
private static IEnumerable<XElement> GetDeclarationsFromElement(XElement container, SrcMLDataContext db) { var name = container.Name; IEnumerable<XElement> declarations; var containersWithoutDeclarations = new HashSet<XName>() { SRC.Class, SRC.Do, SRC.Else, SRC.Enum, SRC.Extern, SRC.If, SRC.Namespace, SRC.Struct, SRC.Switch, SRC.Template, SRC.Then, SRC.Try, SRC.Typedef, SRC.Union, SRC.Unit, SRC.While }; var containersLikeBlocks = new HashSet<XName>() { SRC.Block, SRC.Private, SRC.Protected, SRC.Public }; var methodContainers = new HashSet<XName>(ContainerNames.MethodDefinitions); if (SRC.Catch == name) { declarations = GetDeclarationsFromCatch(container, db); } else if (SRC.For == name) { declarations = GetDeclarationsFromFor(container, db); } else if (methodContainers.Contains(name)) { declarations = GetDeclarationsFromFunction(container, db); } else if (containersLikeBlocks.Contains(name)) { declarations = GetDeclarationsFromBlock(container, db); } else if (containersWithoutDeclarations.Contains(name)) { declarations = Enumerable.Empty<XElement>(); } else { throw new SrcMLRequiredNameException(ContainerNames.All); } var validDeclarations = from decl in declarations where decl.Elements(SRC.Name).Any() select decl; return validDeclarations; }
private static IEnumerable<XElement> GetDeclarationsFromBlock(XElement container, SrcMLDataContext db) { IEnumerable<XElement> declarations = from declaration in container.Elements(SRC.DeclarationStatement) select declaration.Element(SRC.Declaration); return declarations; }
private static IEnumerable<XElement> GetDeclarationsFromCatch(XElement container, SrcMLDataContext db) { IEnumerable<XElement> declarations = from parameter in container.Elements(SRC.Parameter) select parameter.Element(SRC.Declaration); return declarations; }
private static IEnumerable<XElement> GetDeclarationsFromFor(XElement container, SrcMLDataContext db) { IEnumerable<XElement> declarations = container.Element(SRC.Init).Elements(SRC.Declaration); return declarations; }
/// <summary> /// Gets the elements. /// </summary> /// <param name="fileUnit">The file unit.</param> /// <param name="db">The db.</param> /// <returns></returns> internal static IEnumerable<Tuple<string, string>> GetElements(XElement fileUnit, SrcMLDataContext db) { Dictionary<string, Stack<XElement>> currentDeclarations = new Dictionary<string, Stack<XElement>>(); foreach (var scopePairs in GetDeclarationScopesFromContainer(fileUnit, currentDeclarations, db)) { yield return scopePairs; } }
private static IEnumerable<XElement> GetDeclarationsFromFunction(XElement container, SrcMLDataContext db) { IEnumerable<XElement> declarations = from param in container.Element(SRC.ParameterList).Elements(SRC.Parameter) select param.Elements().FirstOrDefault(); foreach (var declaration in declarations) { yield return declaration; } var classNameElement = SrcMLHelper.GetClassNameForMethod(container); if (null != classNameElement) { var className = classNameElement.Value; var classDefinition = (from t in db.Definitions.OfType<TypeDefinition>() where t.TypeName == className select t).FirstOrDefault(); if (null != classDefinition) { var block = classDefinition.Xml.Element(SRC.Block); if (null != block) { foreach (var declaration in GetDeclarationsFromBlock(block, db)) { declaration.AddAnnotation(classDefinition); yield return declaration; } foreach (var name in ContainerNames.ClassSections) { foreach (var child in block.Elements(name)) { foreach (var declaration in GetDeclarationsFromElement(child, db)) { declaration.AddAnnotation(classDefinition); yield return declaration; } } } } } } }
public IEnumerable<TypeDefinition> GetTypeForVariableName(SrcMLDataContext db, XElement typeElement) { if (null == db) throw new ArgumentNullException("db"); if (null == typeElement) throw new ArgumentNullException("typeElement"); SrcMLHelper.ThrowExceptionOnInvalidName(typeElement, SRC.Type); var typeName = typeElement.Elements(SRC.Name).Last().Value; var typeCandidates = from typeDefinition in db.Definitions.OfType<TypeDefinition>() where typeDefinition.Archive == this where typeDefinition.TypeName == typeName select typeDefinition; return typeCandidates; }
private static IEnumerable<Tuple<string, string>> GetDeclarationScopesFromContainer(XElement element, Dictionary<string, Stack<XElement>> currentDeclarations, SrcMLDataContext db) { var allContainerNames = new HashSet<XName>(ContainerNames.All); var declarations = GetDeclarationsFromElement(element, db); // add each variable definition to the appropriate definition stack foreach (var declaration in declarations) { Stack<XElement> stackForName; var name = declaration.Element(SRC.Name).Value; if (currentDeclarations.TryGetValue(name, out stackForName)) { stackForName.Push(declaration); } else { stackForName = new Stack<XElement>(); stackForName.Push(declaration); currentDeclarations[name] = stackForName; } } // add all current variable definitions to the current scope foreach (var definitionStack in currentDeclarations.Values) { yield return new Tuple<string, string>(GetXPath(element), GetXPath(definitionStack.Peek())); } // get all of the child containers var childContainers = from child in element.Elements() where allContainerNames.Contains(child.Name)//ContainerNames.All.Any(c => c == child.ElementXName) select child; // run GetDeclarationScopesFromContainer on each child container foreach (var container in childContainers) { foreach (var childScope in GetDeclarationScopesFromContainer(container, currentDeclarations, db)) { yield return childScope; } } // remove the declarations from their stacks foreach (var declaration in declarations) { var name = declaration.Element(SRC.Name).Value; currentDeclarations[name].Pop(); if (0 == currentDeclarations[name].Count) currentDeclarations.Remove(name); } }