Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 63c23fd

Browse files
committed
Merge branch 'master' of github.com:CTrando/python-language-server into scratch/GenericForwardRef
2 parents 1ff65da + a582f7a commit 63c23fd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+758
-1003
lines changed

README.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,21 @@ The following diagnostics are supported:
2424

2525
| Code | Description |
2626
| - | - |
27+
| `inherit-non-class` | Attempted to inherit something that is not a class. |
2728
| `too-many-function-arguments` | Too many arguments have been provided to a function call. |
2829
| `too-many-positional-arguments-before-star` | Too many arguments have been provided before a starred argument. |
29-
| `positional-argument-after-keyword` | A positional argument has been provided after a keyword argument. |
30-
| `unknown-parameter-name` | The keyword argument name provided is unknown. |
3130
| `parameter-already-specified` | A argument with this name has already been specified. |
3231
| `parameter-missing` | A required positional argument is missing. |
32+
| `positional-argument-after-keyword` | A positional argument has been provided after a keyword argument. |
33+
| `return-in-init` | Encountered an explicit return in `__init__` function. |
34+
| `typing-generic-arguments` | An error occurred while constructing `Generic`. |
35+
| `typing-typevar-arguments` | An error occurred while constructing `TypeVar`. |
36+
| `typing-newtype-arguments` | An error occurred while constructing `NewType`. |
37+
| `unknown-parameter-name` | The keyword argument name provided is unknown. |
3338
| `unresolved-import` | An import cannot be resolved, and may be missing. |
3439
| `undefined-variable` | A variable has used that has not yet been defined. |
40+
| `variable-not-defined-globally` | A variable is not defined in the global scope. |
41+
| `variable-not-defined-nonlocal` | A variable is not defined in non-local scopes. |
3542

3643
[A full list can be seen in the source code.](src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs)
3744

@@ -61,3 +68,11 @@ An example of a user configuration which sets these options:
6168
"python.analysis.disabled": ["too-many-function-arguments", "parameter-missing"],
6269
}
6370
```
71+
72+
Linting can also be controlled on an invidual line basis with a generalized `#noqa`. Lines with `#noqa` will have their diagnostic output suppressed.
73+
74+
An example usage:
75+
76+
```python
77+
from python import language_server # noqa will suppress the linting message for this line
78+
```

TROUBLESHOOTING.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ When filing an issue, make sure you do the following:
9797
This should not be left long term, as the performance impact of the logging is significant.
9898
- State which language server version you are using:
9999
- To find your version: (CTRL + Shift + P >> Python: Create Terminal >> Select "Output" >> Select "Python" from the dropdown menu in the top right of the output window). Look for the line `Microsoft Python Language Server version X` in the console.
100+
- Note: if you are using the Insiders build of VS Code, find your version by navigating to the following: CTRL + Shift + P >> Python: Create Terminal >> Select "Output" >> Select "Python Language Server". Again, you will look for the line `Microsoft Python Language Server version X` in the console.
100101
- State the environment where your code is running; i.e. Python version, the virtual environment type, etc.
101102
- If using a virtual environment, please include the requirements.txt file.
102103
- If working with a conda environment, attach the environment.yml file.

src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Scopes.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,18 @@ public void DeclareVariable(string name, IMember value, VariableSource source)
4343
public void DeclareVariable(string name, IMember value, VariableSource source, IPythonModule module)
4444
=> DeclareVariable(name, value, source, new Location(module));
4545

46-
public void DeclareVariable(string name, IMember value, VariableSource source, Node location, bool overwrite = false)
46+
public void DeclareVariable(string name, IMember value, VariableSource source, Node location, bool overwrite = true)
4747
=> DeclareVariable(name, value, source, GetLocationOfName(location), overwrite);
4848

49-
public void DeclareVariable(string name, IMember value, VariableSource source, Location location, bool overwrite = false) {
49+
public void DeclareVariable(string name, IMember value, VariableSource source, Location location, bool overwrite = true) {
50+
var member = GetInScope(name);
51+
if (member != null && !overwrite) {
52+
return;
53+
}
5054
if (source == VariableSource.Import && value is IVariable v) {
5155
CurrentScope.LinkVariable(name, v, location);
5256
return;
5357
}
54-
var member = GetInScope(name);
5558
if (member != null) {
5659
if (!value.IsUnknown()) {
5760
CurrentScope.DeclareVariable(name, value, source, location);

src/Analysis/Ast/Impl/Analyzer/Handlers/AssignmentHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ private void TryHandleClassVariable(AssignmentStatement node, IMember value) {
111111
var cls = m.GetPythonType<IPythonClassType>();
112112
if (cls != null) {
113113
using (Eval.OpenScope(Eval.Module, cls.ClassDefinition, out _)) {
114-
Eval.DeclareVariable(mex.Name, value, VariableSource.Declaration, Eval.GetLocationOfName(mex), true);
114+
Eval.DeclareVariable(mex.Name, value, VariableSource.Declaration, Eval.GetLocationOfName(mex));
115115
}
116116
}
117117
}

src/Analysis/Ast/Impl/Analyzer/Handlers/FromImportHandler.cs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ private void AssignVariables(FromImportStatement node, IImportSearchResult impor
5959
// TODO: warn this is not a good style per
6060
// TODO: https://docs.python.org/3/faq/programming.html#what-are-the-best-practices-for-using-import-in-a-module
6161
// TODO: warn this is invalid if not in the global scope.
62-
HandleModuleImportStar(variableModule, imports is ImplicitPackageImport);
62+
HandleModuleImportStar(variableModule, imports is ImplicitPackageImport, node.StartIndex);
6363
return;
6464
}
6565

@@ -68,14 +68,16 @@ private void AssignVariables(FromImportStatement node, IImportSearchResult impor
6868
if (!string.IsNullOrEmpty(memberName)) {
6969
var nameExpression = asNames[i] ?? names[i];
7070
var variableName = nameExpression?.Name ?? memberName;
71-
var exported = variableModule.Analysis?.GlobalScope.Variables[memberName] ?? variableModule.GetMember(memberName);
71+
var variable = variableModule.Analysis?.GlobalScope?.Variables[memberName];
72+
var exported = variable ?? variableModule.GetMember(memberName);
7273
var value = exported ?? GetValueFromImports(variableModule, imports as IImportChildrenSource, memberName);
73-
Eval.DeclareVariable(variableName, value, VariableSource.Import, nameExpression);
74+
// Do not allow imported variables to override local declarations
75+
Eval.DeclareVariable(variableName, value, VariableSource.Import, nameExpression, CanOverwriteVariable(variableName, node.StartIndex));
7476
}
7577
}
7678
}
7779

78-
private void HandleModuleImportStar(PythonVariableModule variableModule, bool isImplicitPackage) {
80+
private void HandleModuleImportStar(PythonVariableModule variableModule, bool isImplicitPackage, int importPosition) {
7981
if (variableModule.Module == Module) {
8082
// from self import * won't define any new members
8183
return;
@@ -100,10 +102,31 @@ private void HandleModuleImportStar(PythonVariableModule variableModule, bool is
100102
}
101103

102104
var variable = variableModule.Analysis?.GlobalScope?.Variables[memberName];
103-
Eval.DeclareVariable(memberName, variable ?? member, VariableSource.Import);
105+
// Do not allow imported variables to override local declarations
106+
Eval.DeclareVariable(memberName, variable ?? member, VariableSource.Import, Eval.DefaultLocation, CanOverwriteVariable(memberName, importPosition));
104107
}
105108
}
106109

110+
private bool CanOverwriteVariable(string name, int importPosition) {
111+
var v = Eval.CurrentScope.Variables[name];
112+
if(v == null) {
113+
return true; // Variable does not exist
114+
}
115+
// Allow overwrite if import is below the variable. Consider
116+
// x = 1
117+
// x = 2
118+
// from A import * # brings another x
119+
// x = 3
120+
var references = v.References.Where(r => r.DocumentUri == Module.Uri).ToArray();
121+
if(references.Length == 0) {
122+
// No references to the variable in this file - the variable
123+
// is imported from another module. OK to overwrite.
124+
return true;
125+
}
126+
var firstAssignmentPosition = references.Min(r => r.Span.ToIndexSpan(Ast).Start);
127+
return firstAssignmentPosition < importPosition;
128+
}
129+
107130
private IMember GetValueFromImports(PythonVariableModule parentModule, IImportChildrenSource childrenSource, string memberName) {
108131
if (childrenSource == null || !childrenSource.TryGetChildImport(memberName, out var childImport)) {
109132
return Interpreter.UnknownType;

src/Analysis/Ast/Impl/Analyzer/PythonAnalyzerSession.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ private void LogCanceled(IPythonModule module) {
368368

369369
private void LogException(IPythonModule module, Exception exception) {
370370
if (_log != null) {
371-
_log.Log(TraceEventType.Verbose, $"Analysis of {module.Name}({module.ModuleType}) failed. Exception message: {exception.Message}.");
371+
_log.Log(TraceEventType.Verbose, $"Analysis of {module.Name}({module.ModuleType}) failed. {exception}");
372372
}
373373
}
374374

src/Analysis/Ast/Impl/Analyzer/PythonInterpreter.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,18 @@ private async Task LoadBuiltinTypesAsync(string root, IServiceManager sm, Cancel
4747

4848
sm.AddService(this);
4949
_moduleResolution = new MainModuleResolution(root, sm);
50+
_stubResolution = new TypeshedResolution(sm);
51+
52+
await _moduleResolution.InitializeAsync(cancellationToken);
53+
await _stubResolution.InitializeAsync(cancellationToken);
54+
5055
lock (_lock) {
5156
var builtinModule = _moduleResolution.CreateBuiltinsModule();
5257
_builtinTypes[BuiltinTypeId.NoneType]
5358
= new PythonType("NoneType", new Location(builtinModule), string.Empty, BuiltinTypeId.NoneType);
5459
_builtinTypes[BuiltinTypeId.Unknown]
5560
= UnknownType = new PythonType("Unknown", new Location(builtinModule), string.Empty);
5661
}
57-
await _moduleResolution.InitializeAsync(cancellationToken);
58-
59-
_stubResolution = new TypeshedResolution(sm);
60-
await _stubResolution.InitializeAsync(cancellationToken);
6162

6263
await _moduleResolution.LoadBuiltinTypesAsync(cancellationToken);
6364
}

src/Analysis/Ast/Impl/Analyzer/Symbols/ClassEvaluator.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ private IEnumerable<IPythonType> ProcessBases() {
115115
if (IsValidBase(a)) {
116116
TryAddBase(bases, a);
117117
} else {
118-
ReportInvalidBase(a.ToCodeString(Eval.Ast, CodeFormattingOptions.Traditional));
118+
ReportInvalidBase(a);
119119
}
120120
}
121121

@@ -196,11 +196,11 @@ private void UpdateClassMembers() {
196196
_class.AddMembers(members, false);
197197
}
198198

199-
private void ReportInvalidBase(string argVal) {
199+
private void ReportInvalidBase(Arg arg) {
200200
Eval.ReportDiagnostics(Eval.Module.Uri,
201201
new DiagnosticsEntry(
202-
Resources.InheritNonClass.FormatInvariant(argVal),
203-
_classDef.NameExpression.GetLocation(Eval)?.Span ?? default,
202+
Resources.InheritNonClass.FormatInvariant(arg.ToCodeString(Eval.Ast, CodeFormattingOptions.Traditional)),
203+
Eval.GetLocation(arg)?.Span ?? default,
204204
Diagnostics.ErrorCodes.InheritNonClass,
205205
Severity.Warning,
206206
DiagnosticSource.Analysis

src/Analysis/Ast/Impl/Analyzer/Symbols/FunctionEvaluator.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public override void Evaluate() {
6060
// Do process body of constructors since they may be declaring
6161
// variables that are later used to determine return type of other
6262
// methods and properties.
63-
var ctor = _function.Name.EqualsOrdinal("__init__") || _function.Name.EqualsOrdinal("__new__");
63+
var ctor = _function.IsDunderInit() || _function.IsDunderNew();
6464
if (ctor || returnType.IsUnknown() || Module.ModuleType == ModuleType.User) {
6565
// Return type from the annotation is sufficient for libraries and stubs, no need to walk the body.
6666
FunctionDefinition.Body?.Walk(this);
@@ -119,10 +119,8 @@ public override bool Walk(ReturnStatement node) {
119119
var value = Eval.GetValueFromExpression(node.Expression);
120120
if (value != null) {
121121
// although technically legal, __init__ in a constructor should not have a not-none return value
122-
if (FunctionDefinition.Name.EqualsOrdinal("__init__") && _function.DeclaringType.MemberType == PythonMemberType.Class
123-
&& !value.IsOfType(BuiltinTypeId.NoneType)) {
124-
125-
Eval.ReportDiagnostics(Module.Uri, new Diagnostics.DiagnosticsEntry(
122+
if (_function.IsDunderInit() && !value.IsOfType(BuiltinTypeId.NoneType)) {
123+
Eval.ReportDiagnostics(Module.Uri, new DiagnosticsEntry(
126124
Resources.ReturnInInit,
127125
node.GetLocation(Eval).Span,
128126
ErrorCodes.ReturnInInit,

src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,20 @@
1515

1616
namespace Microsoft.Python.Analysis.Diagnostics {
1717
public static class ErrorCodes {
18+
public const string InheritNonClass = "inherit-non-class";
1819
public const string TooManyFunctionArguments = "too-many-function-arguments";
1920
public const string TooManyPositionalArgumentsBeforeStar = "too-many-positional-arguments-before-star";
20-
public const string PositionalArgumentAfterKeyword = "positional-argument-after-keyword";
21-
public const string UnknownParameterName = "unknown-parameter-name";
2221
public const string ParameterAlreadySpecified = "parameter-already-specified";
2322
public const string ParameterMissing = "parameter-missing";
23+
public const string PositionalArgumentAfterKeyword = "positional-argument-after-keyword";
24+
public const string ReturnInInit = "return-in-init";
25+
public const string TypingGenericArguments = "typing-generic-arguments";
26+
public const string TypingNewTypeArguments = "typing-newtype-arguments";
27+
public const string TypingTypeVarArguments = "typing-typevar-arguments";
28+
public const string UnknownParameterName = "unknown-parameter-name";
2429
public const string UnresolvedImport = "unresolved-import";
2530
public const string UndefinedVariable = "undefined-variable";
2631
public const string VariableNotDefinedGlobally= "variable-not-defined-globally";
2732
public const string VariableNotDefinedNonLocal = "variable-not-defined-nonlocal";
28-
public const string ReturnInInit = "return-in-init";
29-
public const string TypingTypeVarArguments = "typing-typevar-arguments";
30-
public const string TypingNewTypeArguments = "typing-newtype-arguments";
31-
public const string TypingGenericArguments = "typing-generic-arguments";
32-
public const string InheritNonClass = "inherit-non-class";
3333
}
3434
}

0 commit comments

Comments
 (0)