private ILocatedMember GetRootDefinition(ILocatedMember lm) { for (; lm.Parent != null; lm = lm.Parent) { } return(lm); }
private async Task <Reference[]> FindAllReferencesAsync(string name, ILocatedMember rootDefinition, CancellationToken cancellationToken) { var candidateFiles = ScanClosedFiles(name, cancellationToken); await AnalyzeFiles(candidateFiles, cancellationToken); return(rootDefinition.References .Select(r => new Reference { uri = new Uri(r.FilePath), range = r.Span }) .ToArray()); }
public static ILocatedMember GetRootDefinition(this ILocatedMember lm) { if (!(lm is IImportedMember im) || im.Parent == null) { return(lm); } var parent = im.Parent; for (; parent != null;) { if (!(parent is IImportedMember im1) || im1.Parent == null) { break; } parent = im1.Parent; } return(parent); }
public IEnumerable <IReferenceable> GetDefinitions(string name, IMemberContainer innerContainer, IModuleContext context) { IEnumerable <IReferenceable> refs = null; ReferenceDict references; if (_references != null && _references.TryGetValue(name, out references)) { refs = references.Values; } var member = innerContainer.GetMember(context, name); if (member != null) { List <IReferenceable> res; if (refs == null) { res = new List <IReferenceable>(); } else { res = new List <IReferenceable>(refs); } ILocatedMember locatedMember = member as ILocatedMember; if (locatedMember != null) { foreach (var location in locatedMember.Locations) { res.Add(new DefinitionList(location)); } } return(res); } return(new IReferenceable[0]); }
/// <summary> /// Locates definition or declaration of a symbol at the provided location. /// </summary> /// <param name="analysis">Document analysis.</param> /// <param name="location">Location in the document.</param> /// <param name="definingMember">Member location or null of not found.</param> /// <returns>Definition location (module URI and the text range).</returns> public Reference FindDefinition(IDocumentAnalysis analysis, SourceLocation location, out ILocatedMember definingMember) { definingMember = null; if (analysis?.Ast == null) { return(null); } ExpressionLocator.FindExpression(analysis.Ast, location, FindExpressionOptions.Hover, out var exprNode, out var statement, out var exprScope); if (exprNode is ConstantExpression || !(exprNode is Expression expr)) { return(null); // No goto definition for literals. } Reference reference = null; switch (statement) { // Check if this is a relative import case FromImportStatement fromImport: reference = HandleFromImport(analysis, location, fromImport, exprNode, out definingMember); break; case ImportStatement import: reference = HandleImport(analysis, import, exprNode, out definingMember); break; } if (reference != null) { return(reference.uri == null ? null : reference); } var eval = analysis.ExpressionEvaluator; using (eval.OpenScope(analysis.Document, exprScope)) { if (expr is MemberExpression mex) { return(FromMemberExpression(mex, analysis, out definingMember)); } // Try variables var name = (expr as NameExpression)?.Name; if (!string.IsNullOrEmpty(name)) { reference = TryFromVariable(name, analysis, location, statement, out definingMember); } } return(reference); }
private Reference HandleFromImport(IDocumentAnalysis analysis, SourceLocation location, FromImportStatement statement, Node expr, out ILocatedMember definingMember) { definingMember = null; var mres = analysis.Document.Interpreter.ModuleResolution; var imports = mres.CurrentPathResolver.FindImports(analysis.Document.FilePath, statement); IPythonModule module = null; switch (imports) { case ModuleImport moduleImport: module = mres.GetImportedModule(moduleImport.FullName); break; case ImplicitPackageImport packageImport: module = mres.GetImportedModule(packageImport.FullName); break; case ImportNotFound _: return(null); } // Are we in the module name (i.e. A in 'from A import B')? var locationIndex = location.ToIndex(analysis.Ast); if (statement.Root.StartIndex <= locationIndex && locationIndex <= statement.Root.EndIndex) { definingMember = module; return(module != null ? new Reference { range = default, uri = CanNavigateToModule(module) ? module.Uri : null
private async Task <Reference[]> FindAllReferencesAsync(string name, IPythonModule declaringModule, ILocatedMember rootDefinition, SourceLocation location, DefinitionSource definitionSource, CancellationToken cancellationToken) { var candidateFiles = ScanClosedFiles(name, cancellationToken); var reloadRootDefinition = false; if (candidateFiles.Count > 0) { reloadRootDefinition = await AnalyzeFiles(declaringModule.Interpreter.ModuleResolution, candidateFiles, cancellationToken); } if (reloadRootDefinition) { var analysis = await Document.GetAnalysisAsync(declaringModule.Uri, _services, FindReferencesAnalysisTimeout, cancellationToken); var definition = definitionSource.FindDefinition(analysis, location, out var definingMember); if (definition == null) { return(Array.Empty <Reference>()); } rootDefinition = definingMember.GetRootDefinition(); } return(rootDefinition.References .Select(r => new Reference { uri = r.DocumentUri, range = r.Span }) .ToArray()); }
private Reference TryFromVariable(string name, IDocumentAnalysis analysis, SourceLocation location, Node statement, out ILocatedMember member) { member = null; var m = analysis.ExpressionEvaluator.LookupNameInScopes(name, out var scope); if (m != null && scope.Variables[name] is IVariable v) { member = v; var definition = v.Definition; if (statement is ImportStatement || statement is FromImportStatement) { // If we are on the variable definition in this module, // then goto definition should go to the parent, if any. var indexSpan = v.Definition.Span.ToIndexSpan(analysis.Ast); var index = location.ToIndex(analysis.Ast); if (indexSpan.Start <= index && index < indexSpan.End) { if (v.Parent == null) { return(null); } definition = v.Parent.Definition; } } if (CanNavigateToModule(definition.DocumentUri)) { return(new Reference { range = definition.Span, uri = definition.DocumentUri }); } } return(null); }
public Reference FindDefinition(IDocumentAnalysis analysis, SourceLocation location, out ILocatedMember member) { member = null; if (analysis?.Ast == null) { return(null); } ExpressionLocator.FindExpression(analysis.Ast, location, FindExpressionOptions.Hover, out var exprNode, out var statement, out var exprScope); if (exprNode is ConstantExpression || !(exprNode is Expression expr)) { return(null); // No hover for literals. } var eval = analysis.ExpressionEvaluator; using (eval.OpenScope(analysis.Document, exprScope)) { if (expr is MemberExpression mex) { return(FromMemberExpression(mex, analysis, out member)); } // Try variables var name = (expr as NameExpression)?.Name; IMember value = null; if (!string.IsNullOrEmpty(name)) { var reference = TryFromVariable(name, analysis, location, statement, out member); if (reference != null) { return(reference); } if (statement is ImportStatement || statement is FromImportStatement) { reference = TryFromImport(statement, name, analysis, out value); if (reference != null) { member = value as ILocatedMember; return(reference); } } } value = value ?? eval.GetValueFromExpression(expr); if (value.IsUnknown()) { return(null); } member = value as ILocatedMember; return(FromMember(value)); } }
private Reference FromMemberExpression(MemberExpression mex, IDocumentAnalysis analysis, out ILocatedMember member) { member = null; var eval = analysis.ExpressionEvaluator; var target = eval.GetValueFromExpression(mex.Target); var type = target?.GetPythonType(); if (type?.GetMember(mex.Name) is ILocatedMember lm) { member = lm; return(FromMember(lm)); } if (type is IPythonClassType cls) { // Data members may be instances that are not tracking locations. // In this case we'll try look up the respective variable instead. using (eval.OpenScope(analysis.Document, cls.ClassDefinition)) { eval.LookupNameInScopes(mex.Name, out _, out var v, LookupOptions.Local); if (v != null) { member = v; return(FromMember(v)); } } } return(null); }
private Reference FromMemberExpression(MemberExpression mex, IDocumentAnalysis analysis, out ILocatedMember member) { member = null; var eval = analysis.ExpressionEvaluator; var target = eval.GetValueFromExpression(mex.Target); var type = target?.GetPythonType(); switch (type) { case IPythonModule m when m.Analysis.GlobalScope != null: // Module GetMember returns module variable value while we // want the variable itself since we want to know its location. var v1 = m.Analysis.GlobalScope.Variables[mex.Name]; if (v1 != null) { member = v1; return(FromMember(v1)); } break; case IPythonClassType cls: // Data members may be instances that are not tracking locations. // In this case we'll try look up the respective variable instead. using (eval.OpenScope(analysis.Document, cls.ClassDefinition)) { eval.LookupNameInScopes(mex.Name, out _, out var v2, LookupOptions.Local); if (v2 != null) { member = v2; return(FromMember(v2)); } } break; default: if (type?.GetMember(mex.Name) is ILocatedMember lm) { member = lm; return(FromMember(lm)); } break; } return(null); }