Skip to content
This repository was archived by the owner on Apr 14, 2022. It is now read-only.

Store location of module members in the database #1339

Merged
merged 119 commits into from
Jul 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
119 commits
Select commit Hold shift + click to select a range
b605b76
Remove old qualified name
May 17, 2019
5471ce4
Node storage
May 17, 2019
8a8d847
Class and scope to use AST map
May 17, 2019
89ce2ca
Library analysis
May 17, 2019
7a93bf7
Fix SO
May 18, 2019
2a2bdf8
Keep small AST with imports
May 18, 2019
3edaa73
AST reduction
May 18, 2019
73371e1
Final field
May 18, 2019
7d60edc
Initial
May 20, 2019
02475f4
Reload
May 22, 2019
835eeac
Merge master
May 25, 2019
6b6e928
Ignore post-final requests
May 25, 2019
9692397
Drop AST
May 25, 2019
080beab
Remove local variables
May 25, 2019
93a6915
Test fixes
May 26, 2019
cadd7ce
Fix overload match
May 26, 2019
f61b1a7
Tests
May 26, 2019
1b20326
Add locks
May 27, 2019
d7efdac
Remove local variables
May 25, 2019
98934d4
Drop file content to save memory
May 27, 2019
417ae03
Cache PEP hints
May 28, 2019
ec5605f
Recreate AST
May 28, 2019
713d87f
Fix specialization
May 28, 2019
50e63e6
Fix locations
May 28, 2019
fcd0c06
usings
May 28, 2019
f6a992b
Test fixes
May 28, 2019
acad202
Add options to keep data in memory
May 28, 2019
f176b2f
Merge branch 'master' of https://github.com/microsoft/python-language…
May 28, 2019
4225337
Merge master
May 28, 2019
86e36a6
Fix test
May 28, 2019
ba97e9f
Fix lambda parameters
May 28, 2019
ffed87e
Fix argument set
May 29, 2019
186a9c6
Fix overload doc
May 29, 2019
4196699
Fix stub merge errors
May 29, 2019
93249d4
Fix async issues
May 29, 2019
5e61392
Undo some changes
May 29, 2019
130b95d
Fix test
May 29, 2019
a6676f1
Fix race condition
May 30, 2019
18b61ad
Merge master
Jun 1, 2019
0850544
Merge master
Jun 3, 2019
7d0bf5b
Merge branch 'proxymod' into db
Jun 4, 2019
663dc8f
Partial
Jun 4, 2019
86544a6
Models and views
Jun 4, 2019
67b06c2
Merge branch 'master' of https://github.com/microsoft/python-language…
Jun 4, 2019
9daf4a9
Merge master
Jun 4, 2019
90318e9
Restore log null checks
Jun 4, 2019
b79d918
Merge master
Jun 4, 2019
a02c6f3
Fix merge conflict
Jun 4, 2019
8a6b055
Merge master
Jun 5, 2019
57358eb
Fix merge issue
Jun 5, 2019
41ef00f
Merge branch 'master' of https://github.com/microsoft/python-language…
Jun 5, 2019
814cd64
Merge master
Jun 6, 2019
6ceb9b8
Null check
Jun 6, 2019
74bb061
Merge branch 'noast5' into db
Jun 6, 2019
478ce37
Partial
Jun 6, 2019
cb46e68
Partial
Jun 6, 2019
ef2981c
Partial
Jun 6, 2019
2164ad5
Fix test
Jun 6, 2019
1a48790
Merge branch 'noast5' into db
Jun 6, 2019
319c416
Partial
Jun 6, 2019
86b0ee6
Partial
Jun 7, 2019
1670c9d
First test
Jun 7, 2019
ab69cfd
Baseline comparison
Jun 7, 2019
e00c197
Builtins
Jun 7, 2019
4e1657c
Partial
Jun 7, 2019
ade00f4
Type fixes
Jun 10, 2019
e2fc221
Fix type names, part I
Jun 11, 2019
aaf40bb
Qualified name
Jun 11, 2019
a5b3b20
Properly write variables
Jun 11, 2019
f23a487
Partial
Jun 11, 2019
e6373a7
Construct module from model
Jun 12, 2019
6f6737d
Test
Jun 12, 2019
081f475
Variable creations
Jun 12, 2019
42fa4dc
Factories
Jun 13, 2019
2f03cb9
Factories
Jun 13, 2019
1dc3339
Split construction
Jun 13, 2019
9535bad
Restore
Jun 13, 2019
bec2a82
Save builtins
Jun 13, 2019
80c9b1c
Test passes
Jun 13, 2019
5b372f7
Qualified name
Jun 13, 2019
3066554
Better export detection
Jun 14, 2019
91491d4
Test fixes
Jun 14, 2019
bc4f587
More consistent qualified names
Jun 14, 2019
af69880
Sys test
Jun 14, 2019
5c1a0c3
Demo
Jun 14, 2019
4146690
Complete sys write/read
Jun 17, 2019
48763aa
Partial
Jun 17, 2019
93bece3
Partial
Jun 18, 2019
55b6a3f
Test staility
Jun 18, 2019
5e9bf8e
Perf bug
Jun 18, 2019
c152e67
Merge master
Jun 18, 2019
eadd622
Baseline, remove debug code, deactivate db
Jun 18, 2019
ba87581
Test fixes
Jun 18, 2019
a797593
Test fix
Jun 18, 2019
db6c7fc
Simplify a bit
Jun 19, 2019
f73fed0
Baselines and use : separator
Jun 19, 2019
4054d5a
Baselines
Jun 19, 2019
4ef96d8
PR feedback
Jun 19, 2019
c7436ed
Merge branch 'master' of https://github.com/microsoft/python-language…
Jun 19, 2019
f3860e6
Merge master
Jun 19, 2019
cab0fce
Remove registry reference
Jun 19, 2019
b9c1e14
PR feedback
Jun 19, 2019
4fbdcb9
Merge master
Jul 11, 2019
c7b1a5d
Merge db
Jul 11, 2019
90d1429
PR feedback
Jul 11, 2019
10289c3
Merge branch 'master' of https://github.com/microsoft/python-language…
Jul 12, 2019
facb062
Restore persistence + update test
Jul 12, 2019
d80604a
Better handle persistent module in dependencies
Jul 14, 2019
0705812
Merge master
Jul 15, 2019
96a5b82
Merge master
Jul 15, 2019
360f922
Undo
Jul 15, 2019
1015c1b
Add location converter abstraction
Jul 15, 2019
2ab07d6
Store member location
Jul 15, 2019
4779813
Basic locations test
Jul 15, 2019
7e6fb63
Navigation
Jul 15, 2019
9ee9bfe
Add test
Jul 16, 2019
fc66756
Update baselines
Jul 16, 2019
05eb692
Merge branch 'db' of https://github.com/microsoft/python-language-ser…
Jul 23, 2019
5ead9ec
Port changes from dbtype
Jul 25, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Analysis/Ast/Impl/Analyzer/PythonAnalyzerEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ private HashSet<AnalysisModuleKey> FindDependencies(IPythonModule module, Python
}

private static bool Ignore(IModuleManagement moduleResolution, string fullName, string modulePath)
=> moduleResolution.BuiltinModuleName.EqualsOrdinal(fullName) || moduleResolution.GetSpecializedModule(fullName, modulePath) != null;
=> moduleResolution.BuiltinModuleName.EqualsOrdinal(fullName) || moduleResolution.IsSpecializedModule(fullName, modulePath);

private void UpdateAnalysisTcs(int analysisVersion) {
_analysisVersion = analysisVersion;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,10 @@ internal interface IModuleDatabaseService {
/// Writes module data to the database.
/// </summary>
Task StoreModuleAnalysisAsync(IDocumentAnalysis analysis, CancellationToken cancellationToken = default);

/// <summary>
/// Determines if module analysis exists in the storage.
/// </summary>
bool ModuleExistsInStorage(string moduleName, string filePath);
}
}
2 changes: 1 addition & 1 deletion src/Analysis/Ast/Impl/Extensions/PythonModuleExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
namespace Microsoft.Python.Analysis {
public static class PythonModuleExtensions {
internal static PythonAst GetAst(this IPythonModule module)
=> (PythonAst)((IAstNodeContainer)module).GetAstNode(module);
=> (PythonAst)(module as IAstNodeContainer)?.GetAstNode(module);

internal static void SetAst(this IPythonModule module, PythonAst ast) {
var contained = (IAstNodeContainer)module;
Expand Down
13 changes: 9 additions & 4 deletions src/Analysis/Ast/Impl/Modules/Definitions/IModuleManagement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,20 @@ public interface IModuleManagement: IModuleResolution {
/// content is loaded and analyzed only for class/functions definitions
/// so the original documentation can be extracted.
/// </summary>
/// <param name="name">Module to specialize.</param>
/// <param name="fullName">Module to specialize.</param>
/// <param name="specializationConstructor">Specialized module constructor.</param>
/// <returns>Original (library) module loaded as stub, if any.</returns>
IPythonModule SpecializeModule(string name, Func<string, IPythonModule> specializationConstructor);
IPythonModule SpecializeModule(string fullName, Func<string, IPythonModule> specializationConstructor);

/// <summary>
/// Returns specialized module, if any.
/// Returns specialized module, if any. Will attempt to load module from persistent state.
/// </summary>
IPythonModule GetSpecializedModule(string name, string modulePath = null);
IPythonModule GetSpecializedModule(string fullName, bool allowCreation = false, string modulePath = null);

/// <summary>
/// Determines of module is specialized or exists in the database.
/// </summary>
bool IsSpecializedModule(string fullName, string modulePath = null);

/// <summary>
/// Root directory of the path resolver.
Expand Down
7 changes: 6 additions & 1 deletion src/Analysis/Ast/Impl/Modules/PythonModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ namespace Microsoft.Python.Analysis.Modules {
/// to AST and the module analysis.
/// </summary>
[DebuggerDisplay("{Name} : {ModuleType}")]
internal class PythonModule : LocatedMember, IDocument, IAnalyzable, IEquatable<IPythonModule>, IAstNodeContainer {
internal class PythonModule : LocatedMember, IDocument, IAnalyzable, IEquatable<IPythonModule>, IAstNodeContainer, ILocationConverter {
private enum State {
None,
Loading,
Expand Down Expand Up @@ -565,6 +565,11 @@ private string TryGetDocFromModuleInitFile() {
}
#endregion

#region ILocationConverter
public virtual SourceLocation IndexToLocation(int index) => this.GetAst()?.IndexToLocation(index) ?? default;
public virtual int LocationToIndex(SourceLocation location) => this.GetAst()?.LocationToIndex(location) ?? default;
#endregion

private void RemoveReferencesInModule(IPythonModule module) {
if (module.GlobalScope?.Variables != null) {
foreach (var v in module.GlobalScope.Variables) {
Expand Down
8 changes: 7 additions & 1 deletion src/Analysis/Ast/Impl/Modules/PythonVariableModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,15 @@
using Microsoft.Python.Analysis.Types;
using Microsoft.Python.Analysis.Values;
using Microsoft.Python.Core;
using Microsoft.Python.Core.Text;

namespace Microsoft.Python.Analysis.Modules {
/// <summary>
/// Module-scoped representation of the module or implicit package
/// Contains either module members, members + imported children of explicit package or imported implicit package children
/// Instance is unique for each module analysis
/// </summary>
internal sealed class PythonVariableModule : LocatedMember, IPythonModule, IEquatable<IPythonModule> {
internal sealed class PythonVariableModule : LocatedMember, IPythonModule, IEquatable<IPythonModule>, ILocationConverter {
private readonly Dictionary<string, PythonVariableModule> _children = new Dictionary<string, PythonVariableModule>();

public string Name { get; }
Expand Down Expand Up @@ -71,5 +72,10 @@ public PythonVariableModule(IPythonModule module): base(module) {
public IMember CreateInstance(string typeName = null, IArgumentSet args = null) => this;

public bool Equals(IPythonModule other) => other is PythonVariableModule module && Name.EqualsOrdinal(module.Name);

#region ILocationConverter
public SourceLocation IndexToLocation(int index) => (Module as ILocationConverter)?.IndexToLocation(index) ?? default;
public int LocationToIndex(SourceLocation location) => (Module as ILocationConverter)?.LocationToIndex(location) ?? default;
#endregion
}
}
28 changes: 16 additions & 12 deletions src/Analysis/Ast/Impl/Modules/Resolution/MainModuleResolution.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,21 @@ protected override IPythonModule CreateModule(string name) {
return null;
}

IPythonModule module;
if (moduleImport.ModulePath != null) {
var module = GetRdt().GetDocument(new Uri(moduleImport.ModulePath));
module = GetRdt().GetDocument(new Uri(moduleImport.ModulePath));
if (module != null) {
GetRdt().LockDocument(module.Uri);
return module;
}
}

var dbs = GetDbService();
if (dbs != null && dbs.TryCreateModule(name, moduleImport.ModulePath, out module) != ModuleStorageState.DoesNotExist && module != null) {
SpecializeModule(name, s => module);
return module;
}

// If there is a stub, make sure it is loaded and attached
// First check stub next to the module.
if (!TryCreateModuleStub(name, moduleImport.ModulePath, out var stub)) {
Expand Down Expand Up @@ -152,17 +159,14 @@ public IPythonModule SpecializeModule(string name, Func<string, IPythonModule> s
/// <summary>
/// Returns specialized module, if any.
/// </summary>
public IPythonModule GetSpecializedModule(string fullName, string modulePath = null) {
if (_specialized.TryGetValue(fullName, out var module)) {
return module;
}
var dbs = GetDbService();
if (dbs != null && dbs.TryCreateModule(fullName, modulePath, out module) != ModuleStorageState.DoesNotExist && module != null) {
SpecializeModule(fullName, s => module);
return module;
}
return null;
}
public IPythonModule GetSpecializedModule(string fullName, bool allowCreation = false, string modulePath = null)
=> _specialized.TryGetValue(fullName, out var module) ? module : null;

/// <summary>
/// Determines of module is specialized or exists in the database.
/// </summary>
public bool IsSpecializedModule(string fullName, string modulePath = null)
=> _specialized.ContainsKey(fullName) || GetDbService()?.ModuleExistsInStorage(fullName, modulePath) == true;

internal async Task LoadBuiltinTypesAsync(CancellationToken cancellationToken = default) {
var analyzer = _services.GetService<IPythonAnalyzer>();
Expand Down
16 changes: 13 additions & 3 deletions src/Analysis/Ast/Impl/Modules/Resolution/ModuleResolutionBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,25 @@ public IPythonModule GetImportedModule(string name)
=> Modules.TryGetValue(name, out var moduleRef) ? moduleRef.Value : _interpreter.ModuleResolution.GetSpecializedModule(name);

public IPythonModule GetOrLoadModule(string name) {
if (Modules.TryGetValue(name, out var moduleRef)) {
return moduleRef.GetOrCreate(name, this);
// Specialized should always win. However, we don't want
// to allow loading from the database just yet since module
// may already exist in the analyzed state.
var module = GetImportedModule(name);
if (module != null) {
return module;
}

var module = _interpreter.ModuleResolution.GetSpecializedModule(name);
// Now try restoring from the database.
module = _interpreter.ModuleResolution.GetSpecializedModule(name, true);
if (module != null) {
return module;
}

// Now try regular case.
if (Modules.TryGetValue(name, out var moduleRef)) {
return moduleRef.GetOrCreate(name, this);
}

moduleRef = Modules.GetOrAdd(name, new ModuleRef());
return moduleRef.GetOrCreate(name, this);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Analysis/Ast/Impl/Types/ArgumentSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ private IMember GetArgumentValue(Argument arg) {
}

if (arg.ValueIsDefault) {
using (Eval.OpenScope(DeclaringModule.Analysis.GlobalScope)) {
using (Eval.OpenScope(DeclaringModule.GlobalScope)) {
return Eval.GetValueFromExpression(arg.ValueExpression) ?? Eval.UnknownType;
}
}
Expand Down
5 changes: 2 additions & 3 deletions src/Analysis/Ast/Impl/Types/Location.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,8 @@ public Location(IPythonModule module, IndexSpan indexSpan) {

public LocationInfo LocationInfo {
get {
var ast = Module?.GetAst();
if (ast != null && !string.IsNullOrEmpty(Module?.FilePath) && Module?.Uri != null) {
return new LocationInfo(Module.FilePath, Module.Uri, IndexSpan.ToSourceSpan(ast));
if (Module is ILocationConverter lc && !string.IsNullOrEmpty(Module?.FilePath) && Module?.Uri != null) {
return new LocationInfo(Module.FilePath, Module.Uri, IndexSpan.ToSourceSpan(lc));
}
return LocationInfo.Empty;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Analysis/Ast/Impl/Types/PythonFunctionOverload.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ private IMember CreateSpecificReturnFromTypeVar(IPythonClassType selfClassType,
// Try returning the constraint
// TODO: improve this, the heuristic is pretty basic and tailored to simple func(_T) -> _T
var name = StaticReturnValue.GetPythonType()?.Name;
var typeDefVar = DeclaringModule.Analysis.GlobalScope.Variables[name];
var typeDefVar = DeclaringModule.GlobalScope.Variables[name];
if (typeDefVar?.Value is IGenericTypeDefinition gtp2) {
// See if the instance (self) type satisfies one of the constraints.
return selfClassType.Mro.Any(b => gtp2.Constraints.Any(c => c.Equals(b)))
Expand Down
27 changes: 27 additions & 0 deletions src/Caching/Impl/Extensions/IndexSpanExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Python Tools for Visual Studio
// Copyright(c) Microsoft Corporation
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the License); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
// MERCHANTABILITY OR NON-INFRINGEMENT.
//
// See the Apache Version 2.0 License for specific language governing
// permissions and limitations under the License.

using Microsoft.Python.Analysis.Caching.Models;
using Microsoft.Python.Core.Text;

namespace Microsoft.Python.Analysis.Caching {
internal static class IndexSpanExtensions {
public static IndexSpanModel ToModel(this IndexSpan span) => new IndexSpanModel {
Start = span.Start,
Length = span.Length
};
}
}
2 changes: 1 addition & 1 deletion src/Caching/Impl/Factories/ClassFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public ClassFactory(IEnumerable<ClassModel> classes, ModuleFactory mf)
}

protected override PythonClassType CreateMember(ClassModel cm, IPythonType declaringType)
=> new PythonClassType(cm.Name, ModuleFactory.DefaultLocation);
=> new PythonClassType(cm.Name, new Location(ModuleFactory.Module, cm.IndexSpan.ToSpan()));

protected override void CreateMemberParts(ClassModel cm, PythonClassType cls) {
// In Python 3 exclude object since type creation will add it automatically.
Expand Down
4 changes: 2 additions & 2 deletions src/Caching/Impl/Factories/FunctionFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ public FunctionFactory(IEnumerable<FunctionModel> classes, ModuleFactory mf)
}

protected override IPythonFunctionType CreateMember(FunctionModel fm, IPythonType declaringType) {
var f = new PythonFunctionType(fm.Name, ModuleFactory.DefaultLocation, declaringType, fm.Documentation);
var f = new PythonFunctionType(fm.Name, new Location(ModuleFactory.Module, fm.IndexSpan.ToSpan()), declaringType, fm.Documentation);
foreach (var om in fm.Overloads) {
var o = new PythonFunctionOverload(fm.Name, ModuleFactory.DefaultLocation);
var o = new PythonFunctionOverload(fm.Name, new Location(ModuleFactory.Module, fm.IndexSpan.ToSpan()));
o.SetDocumentation(fm.Documentation);
o.SetReturnValue(ModuleFactory.ConstructMember(om.ReturnType), true);
o.SetParameters(om.Parameters.Select(ConstructParameter).ToArray());
Expand Down
2 changes: 1 addition & 1 deletion src/Caching/Impl/Factories/PropertyFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public PropertyFactory(ModuleFactory mf) {
}

public IPythonPropertyType Construct(PropertyModel pm, IPythonClassType cls) {
var prop = new PythonPropertyType(pm.Name, _mf.DefaultLocation, cls, (pm.Attributes & FunctionAttributes.Abstract) != 0);
var prop = new PythonPropertyType(pm.Name, new Location(_mf.Module, pm.IndexSpan.ToSpan()), cls, (pm.Attributes & FunctionAttributes.Abstract) != 0);
prop.SetDocumentation(pm.Documentation);
var o = new PythonFunctionOverload(pm.Name, _mf.DefaultLocation);
o.SetDocumentation(pm.Documentation); // TODO: own documentation?
Expand Down
2 changes: 1 addition & 1 deletion src/Caching/Impl/Factories/VariableFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public VariableFactory(IEnumerable<VariableModel> models, ModuleFactory mf)

protected override IVariable CreateMember(VariableModel vm, IPythonType declaringType) {
var m = ModuleFactory.ConstructMember(vm.Value);
return new Variable(vm.Name, m, VariableSource.Declaration, ModuleFactory.DefaultLocation);
return new Variable(vm.Name, m, VariableSource.Declaration, new Location(ModuleFactory.Module, vm.IndexSpan.ToSpan()));
}
}
}
2 changes: 2 additions & 0 deletions src/Caching/Impl/Models/ClassModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ private ClassModel(IPythonClassType cls) {

Name = cls.TypeId == BuiltinTypeId.Ellipsis ? "ellipsis" : cls.Name;
Id = Name.GetStableHash();
IndexSpan = cls.Location.IndexSpan.ToModel();

Documentation = cls.Documentation;
Bases = cls.Bases.OfType<IPythonClassType>().Select(t => t.GetQualifiedName()).ToArray();
Methods = methods.ToArray();
Expand Down
1 change: 1 addition & 0 deletions src/Caching/Impl/Models/FunctionModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public static FunctionModel FromType(IPythonFunctionType ft) {
return new FunctionModel {
Id = ft.Name.GetStableHash(),
Name = ft.Name,
IndexSpan = ft.Location.IndexSpan.ToModel(),
Documentation = ft.Documentation,
Overloads = ft.Overloads.Select(FromOverload).ToArray()
// TODO: attributes, inner functions and inner classes.
Expand Down
26 changes: 26 additions & 0 deletions src/Caching/Impl/Models/IndexSpanModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Python Tools for Visual Studio
// Copyright(c) Microsoft Corporation
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the License); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
// MERCHANTABILITY OR NON-INFRINGEMENT.
//
// See the Apache Version 2.0 License for specific language governing
// permissions and limitations under the License.

using Microsoft.Python.Core.Text;

namespace Microsoft.Python.Analysis.Caching.Models {
internal sealed class IndexSpanModel {
public int Start { get; set; }
public int Length { get; set; }

public IndexSpan ToSpan() => new IndexSpan(Start, Length);
}
}
3 changes: 3 additions & 0 deletions src/Caching/Impl/Models/MemberModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@
// See the Apache Version 2.0 License for specific language governing
// permissions and limitations under the License.

using Microsoft.Python.Core.Text;

namespace Microsoft.Python.Analysis.Caching.Models {
internal abstract class MemberModel {
public int Id { get; set; }
public string Name { get; set; }
public IndexSpanModel IndexSpan { get; set; }
}
}
28 changes: 25 additions & 3 deletions src/Caching/Impl/Models/ModuleModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,31 @@
using Microsoft.Python.Analysis.Types;
using Microsoft.Python.Analysis.Values;
using Microsoft.Python.Core;
using Microsoft.Python.Parsing;

namespace Microsoft.Python.Analysis.Caching.Models {
internal sealed class ModuleModel : MemberModel {
/// <summary>
/// Module unique id that includes version.
/// </summary>
public string UniqueId { get; set; }

public string Documentation { get; set; }
public FunctionModel[] Functions { get; set; }
public VariableModel[] Variables { get; set; }
public ClassModel[] Classes { get; set; }

/// <summary>
/// Collection of new line information for conversion of linear spans
/// to line/columns in navigation to member definitions and references.
/// </summary>
public NewLineModel[] NewLines { get; set; }

/// <summary>
/// Length of the original module file. Used in conversion of indices to line/columns.
/// </summary>
public int FileSize { get; set; }

// TODO: TypeVars, ...

public static ModuleModel FromAnalysis(IDocumentAnalysis analysis, IServiceContainer services) {
Expand All @@ -42,15 +59,15 @@ public static ModuleModel FromAnalysis(IDocumentAnalysis analysis, IServiceConta
string typeName = null;

switch (v.Value) {
case IPythonFunctionType ft
case IPythonFunctionType ft
when ft.DeclaringModule.Equals(analysis.Document) || ft.DeclaringModule.Equals(analysis.Document.Stub):
if (!functions.ContainsKey(ft.Name)) {
typeName = ft.Name;
functions[ft.Name] = FunctionModel.FromType(ft);
}

break;
case IPythonClassType cls
case IPythonClassType cls
when cls.DeclaringModule.Equals(analysis.Document) || cls.DeclaringModule.Equals(analysis.Document.Stub):
if (!classes.ContainsKey(cls.Name)) {
typeName = cls.Name;
Expand All @@ -73,7 +90,12 @@ when cls.DeclaringModule.Equals(analysis.Document) || cls.DeclaringModule.Equals
Documentation = analysis.Document.Documentation,
Functions = functions.Values.ToArray(),
Variables = variables.Values.ToArray(),
Classes = classes.Values.ToArray()
Classes = classes.Values.ToArray(),
NewLines = analysis.Ast.NewLineLocations.Select(l => new NewLineModel {
EndIndex = l.EndIndex,
Kind = l.Kind
}).ToArray(),
FileSize = analysis.Ast.EndIndex
};
}
}
Expand Down
Loading