From a5faba091416e6635843d4ff9fa9097352926e5a Mon Sep 17 00:00:00 2001 From: Cameron Trando Date: Fri, 21 Jun 2019 12:55:56 -0700 Subject: [PATCH 01/10] Adding diagnostic message for improperly using Generic --- .../Evaluation/ExpressionEval.Generics.cs | 71 ++++-- .../ExpressionEval.Generics.cs.orig | 241 ++++++++++++++++++ .../Ast/Impl/Diagnostics/ErrorCodes.cs | 1 + .../Ast/Impl/Diagnostics/ErrorCodes.cs.orig | 34 +++ src/Analysis/Ast/Impl/Resources.Designer.cs | 18 ++ src/Analysis/Ast/Impl/Resources.resx | 8 +- src/Analysis/Ast/Impl/Resources.resx.orig | 203 +++++++++++++++ src/Analysis/Ast/Test/LintGenericTests.cs | 76 ++++++ 8 files changed, 628 insertions(+), 24 deletions(-) create mode 100644 src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs.orig create mode 100644 src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs.orig create mode 100644 src/Analysis/Ast/Impl/Resources.resx.orig create mode 100644 src/Analysis/Ast/Test/LintGenericTests.cs diff --git a/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs b/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs index f815271f7..2b1db85a9 100644 --- a/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs +++ b/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs @@ -16,12 +16,15 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Python.Analysis.Diagnostics; using Microsoft.Python.Analysis.Specializations.Typing; using Microsoft.Python.Analysis.Specializations.Typing.Types; using Microsoft.Python.Analysis.Types; using Microsoft.Python.Analysis.Values; using Microsoft.Python.Core; +using Microsoft.Python.Parsing; using Microsoft.Python.Parsing.Ast; +using ErrorCodes = Microsoft.Python.Analysis.Diagnostics.ErrorCodes; namespace Microsoft.Python.Analysis.Analyzer.Evaluation { internal sealed partial class ExpressionEval { @@ -59,40 +62,62 @@ private IMember GetValueFromGeneric(IMember target, Expression expr) { } /// - /// Given generic type and list of indices in the expression like - /// Generic[T1, T2, ...] or List[str] creates generic class base - /// (if the former) on specific type (if the latter). + /// Returns whether the arguments to Generic are valid /// - private IMember CreateSpecificTypeFromIndex(IGenericType gt, IReadOnlyList indices, Expression expr) { - // See which ones are generic parameters as defined by TypeVar() - // and which are specific types. Normally there should not be a mix. - var genericTypeArgs = indices.OfType().ToArray(); - var specificTypes = indices.Where(i => !(i is IGenericTypeDefinition)).OfType().ToArray(); - - if (genericTypeArgs.Length > 0 && genericTypeArgs.Length != indices.Count) { - // TODO: report that some type arguments are not declared with TypeVar. + private bool GenericClassParameterValid(IGenericTypeDefinition[] genericTypeArgs, IReadOnlyList indices, Expression expr) { + if (genericTypeArgs.Length == 0) { + return false; } - if (specificTypes.Length > 0 && specificTypes.Length != indices.Count) { - // TODO: report that arguments are not specific types or are not declared. + + // All arguments to Generic must be type parameters + // e.g. Generic[T, str] throws a runtime error + if (genericTypeArgs.Length != indices.Count) { + ReportDiagnostics(Module.Uri, new DiagnosticsEntry( + Resources.GenericArgumentsNotAllTypeParameters, + GetLocation(expr).Span, + ErrorCodes.GenericArguments, + Severity.Error, + DiagnosticSource.Analysis)); + return false; + } + + // All arguments to Generic must be distinct + if (genericTypeArgs.Distinct().Count() != genericTypeArgs.Length) { + ReportDiagnostics(Module.Uri, new DiagnosticsEntry( + Resources.GenericArgumentsNotAllUnique, + GetLocation(expr).Span, + ErrorCodes.GenericArguments, + Severity.Error, + DiagnosticSource.Analysis)); + return false; } + return true; + } + + /// + /// Given generic type and list of arguments in the expression like + /// Generic[T1, T2, ...] or List[str] creates generic class base + /// (if the former) on specific type (if the latter). + /// + private IMember CreateSpecificTypeFromIndex(IGenericType gt, IReadOnlyList args, Expression expr) { + var genericTypeArgs = args.OfType().ToArray(); + if (gt.Name.EqualsOrdinal("Generic")) { - // Generic[T1, T2, ...] expression. Create generic base for the class. - if (genericTypeArgs.Length > 0) { - return new GenericClassParameter(genericTypeArgs, Module); - } else { - // TODO: report too few type arguments for Generic[]. + if (!GenericClassParameterValid(genericTypeArgs, args, expr)) { return UnknownType; } + + // Generic[T1, T2, ...] expression. Create generic base for the class. + return new GenericClassParameter(genericTypeArgs, Module); } // For other types just use supplied arguments - if (indices.Count > 0) { - return gt.CreateSpecificType(new ArgumentSet(indices, expr, this)); + if (args.Count > 0) { + return gt.CreateSpecificType(new ArgumentSet(args, expr, this)); } - // TODO: report too few type arguments for the generic expression. - return UnknownType; + return UnknownType; } private IReadOnlyList EvaluateIndex(IndexExpression expr) { @@ -194,7 +219,7 @@ private static IReadOnlyList GetSpecificTypeFromArgumentValue(objec var itemType = iter.GetIterator().Next.GetPythonType(); if (!itemType.IsUnknown()) { specificTypes.Add(itemType); - } else if(argumentValue is IPythonInstance inst) { + } else if (argumentValue is IPythonInstance inst) { specificTypes.Add(inst.GetPythonType()); } break; diff --git a/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs.orig b/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs.orig new file mode 100644 index 000000000..c52c15b8c --- /dev/null +++ b/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs.orig @@ -0,0 +1,241 @@ +// 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 System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Python.Analysis.Diagnostics; +using Microsoft.Python.Analysis.Specializations.Typing; +using Microsoft.Python.Analysis.Specializations.Typing.Types; +using Microsoft.Python.Analysis.Types; +using Microsoft.Python.Analysis.Values; +using Microsoft.Python.Core; +using Microsoft.Python.Core.Text; +using Microsoft.Python.Parsing; +using Microsoft.Python.Parsing.Ast; +using ErrorCodes = Microsoft.Python.Analysis.Diagnostics.ErrorCodes; + +namespace Microsoft.Python.Analysis.Analyzer.Evaluation { + internal sealed partial class ExpressionEval { + /// + /// Creates specific type from expression that involves generic type + /// and the specific type arguments, such as Generic[T] or constructor + /// of a generic class. + /// + private IMember GetValueFromGeneric(IMember target, Expression expr) { + if (!(target is PythonClassType c && c.IsGeneric()) && !(target is IGenericType)) { + return null; + } + + using (OpenScope(target.GetPythonType()?.DeclaringModule, GetScope(target), out _)) { + // Try generics + // Evaluate index to check if the result is a generic parameter. + // If it is, then this is a declaration expression such as Generic[T] + // rather than specific type instantiation as in List[str]. + switch (expr) { + // Indexing returns type as from A[int] + case IndexExpression indexExpr when target is IGenericType gt: + // Generic[T1, T2, ...] + var indices = EvaluateIndex(indexExpr); + return CreateSpecificTypeFromIndex(gt, indices, expr); + + case CallExpression callExpr when target is PythonClassType c1: + // Alternative instantiation: + // class A(Generic[T]): ... + // x = A(1234) + var arguments = EvaluateCallArgs(callExpr).ToArray(); + return CreateClassInstance(c1, arguments, callExpr); + } + } + return null; + } + + /// + /// Returns whether the arguments to Generic are valid + /// + private bool GenericClassParameterValid(IGenericTypeDefinition[] genericTypeArgs, IReadOnlyList indices, Expression expr) { + if (genericTypeArgs.Length == 0) { + return false; + } + + // All arguments to Generic must be type parameters + // e.g. Generic[T, str] throws a runtime error + if (genericTypeArgs.Length != indices.Count) { + ReportDiagnostics(Module.Uri, new DiagnosticsEntry( + Resources.GenericArgumentsNotAllTypeParameters, + GetLocation(expr).Span, + ErrorCodes.GenericArguments, + Severity.Error, + DiagnosticSource.Analysis)); + return false; + } + + // All arguments to Generic must be distinct + if (genericTypeArgs.Distinct().Count() != genericTypeArgs.Length) { + ReportDiagnostics(Module.Uri, new DiagnosticsEntry( + Resources.GenericArgumentsNotAllUnique, + GetLocation(expr).Span, + ErrorCodes.GenericArguments, + Severity.Error, + DiagnosticSource.Analysis)); + return false; + } + + return true; + } + + /// + /// Given generic type and list of arguments in the expression like + /// Generic[T1, T2, ...] or List[str] creates generic class base + /// (if the former) on specific type (if the latter). + /// + private IMember CreateSpecificTypeFromIndex(IGenericType gt, IReadOnlyList args, Expression expr) { + var genericTypeArgs = args.OfType().ToArray(); + + if (gt.Name.EqualsOrdinal("Generic")) { + if (!GenericClassParameterValid(genericTypeArgs, args, expr)) { + return UnknownType; + } + + // Generic[T1, T2, ...] expression. Create generic base for the class. + return new GenericClassParameter(genericTypeArgs, Module); + } + + // For other types just use supplied arguments +<<<<<<< HEAD + if (indices.Count > 0) { + return gt.CreateSpecificType(new ArgumentSet(indices, expr, this)); +======= + if (args.Count > 0) { + return gt.CreateSpecificType(new ArgumentSet(args)); +>>>>>>> Adding diagnostic message for improperly using Generic + } + + return UnknownType; + } + + private IReadOnlyList EvaluateIndex(IndexExpression expr) { + var indices = new List(); + if (expr.Index is TupleExpression tex) { + foreach (var item in tex.Items) { + var e = GetValueFromExpression(item); + indices.Add(e); + } + } else { + var index = GetValueFromExpression(expr.Index); + indices.Add(index ?? UnknownType); + } + return indices; + } + + private IReadOnlyList EvaluateCallArgs(CallExpression expr) { + var indices = new List(); + foreach (var e in expr.Args.Select(a => a.Expression)) { + var value = GetValueFromExpression(e) ?? UnknownType; + indices.Add(value); + } + return indices; + } + + /// + /// Given generic class type and the passed constructor arguments + /// creates specific type and instance of the type. Attempts to match + /// supplied arguments to either __init__ signature or to the + /// list of generic definitions in Generic[T1, T2, ...]. + /// + private IMember CreateClassInstance(PythonClassType cls, IReadOnlyList constructorArguments, CallExpression callExpr) { + // Look at the constructor arguments and create argument set + // based on the __init__ definition. + var initFunc = cls.GetMember(@"__init__") as IPythonFunctionType; + var initOverload = initFunc?.DeclaringType == cls ? initFunc.Overloads.FirstOrDefault() : null; + + var argSet = initOverload != null + ? new ArgumentSet(initFunc, 0, null, callExpr, this) + : new ArgumentSet(constructorArguments, callExpr, this); + + argSet.Evaluate(); + var specificType = cls.CreateSpecificType(argSet); + return new PythonInstance(specificType); + } + + private ScopeStatement GetScope(IMember m) { + switch (m.GetPythonType()) { + case IPythonClassType ct: + return ct.ClassDefinition; + case IPythonFunctionType ct: + return ct.FunctionDefinition; + } + return null; + } + + public static IReadOnlyList GetTypeArgumentsFromParameters(IPythonFunctionOverload o, IArgumentSet args) { + if (o.Parameters.Any(p => p.IsGeneric)) { + // Declaring class is not generic, but the function is and arguments + // should provide actual specific types. + // TODO: handle keyword and dict args + var list = new List(); + for (var i = 0; i < Math.Min(o.Parameters.Count, args.Arguments.Count); i++) { + if (o.Parameters[i].IsGeneric) { + list.AddRange(GetSpecificTypeFromArgumentValue(args.Arguments[i].Value)); + } + } + return list; + } + return null; + } + + /// + /// Given argument attempts to extract specific types for the function generic + /// parameter(s). Handles common cases such as dictionary, list and tuple. + /// Typically used on a value that is being passed to the function in place + /// of the generic parameter. + /// + /// + /// Consider 'def func(x: Mapping[K, V]) -> K: ...' + /// + private static IReadOnlyList GetSpecificTypeFromArgumentValue(object argumentValue) { + var specificTypes = new List(); + switch (argumentValue) { + case IPythonDictionary dict: + var keyType = dict.Keys.FirstOrDefault()?.GetPythonType(); + var valueType = dict.Values.FirstOrDefault()?.GetPythonType(); + if (!keyType.IsUnknown()) { + specificTypes.Add(keyType); + } + if (!valueType.IsUnknown()) { + specificTypes.Add(valueType); + } + break; + case IPythonCollection coll: + specificTypes.AddRange(coll.Contents.Select(m => m.GetPythonType())); + break; + case IPythonIterable iter: + var itemType = iter.GetIterator().Next.GetPythonType(); + if (!itemType.IsUnknown()) { + specificTypes.Add(itemType); + } else if (argumentValue is IPythonInstance inst) { + specificTypes.Add(inst.GetPythonType()); + } + break; + case IMember m: + if (!m.IsUnknown()) { + specificTypes.Add(m.GetPythonType()); + } + break; + } + return specificTypes; + } + } +} diff --git a/src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs b/src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs index fdf6f03f8..7996edd80 100644 --- a/src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs +++ b/src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs @@ -26,5 +26,6 @@ public static class ErrorCodes { public const string VariableNotDefinedGlobally= "variable-not-defined-globally"; public const string VariableNotDefinedNonLocal = "variable-not-defined-nonlocal"; public const string ReturnInInit = "return-in-init"; + public const string GenericArguments = "generic-arguments"; } } diff --git a/src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs.orig b/src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs.orig new file mode 100644 index 000000000..31347af00 --- /dev/null +++ b/src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs.orig @@ -0,0 +1,34 @@ +// 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. + +namespace Microsoft.Python.Analysis.Diagnostics { + public static class ErrorCodes { + public const string TooManyFunctionArguments = "too-many-function-arguments"; + public const string TooManyPositionalArgumentsBeforeStar = "too-many-positional-arguments-before-star"; + public const string PositionalArgumentAfterKeyword = "positional-argument-after-keyword"; + public const string UnknownParameterName = "unknown-parameter-name"; + public const string ParameterAlreadySpecified = "parameter-already-specified"; + public const string ParameterMissing = "parameter-missing"; + public const string UnresolvedImport = "unresolved-import"; + public const string UndefinedVariable = "undefined-variable"; + public const string VariableNotDefinedGlobally= "variable-not-defined-globally"; + public const string VariableNotDefinedNonLocal = "variable-not-defined-nonlocal"; +<<<<<<< HEAD + public const string ReturnInInit = "return-in-init"; +======= + public const string GenericArguments = "generic-arguments"; +>>>>>>> Adding diagnostic message for improperly using Generic + } +} diff --git a/src/Analysis/Ast/Impl/Resources.Designer.cs b/src/Analysis/Ast/Impl/Resources.Designer.cs index 365bba623..d8333af03 100644 --- a/src/Analysis/Ast/Impl/Resources.Designer.cs +++ b/src/Analysis/Ast/Impl/Resources.Designer.cs @@ -222,6 +222,24 @@ internal static string ExceptionGettingSearchPaths { } } + /// + /// Looks up a localized string similar to Arguments to Generic must all be type parameters.. + /// + internal static string GenericArgumentsNotAllTypeParameters { + get { + return ResourceManager.GetString("GenericArgumentsNotAllTypeParameters", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Arguments to Generic must all be unique.. + /// + internal static string GenericArgumentsNotAllUnique { + get { + return ResourceManager.GetString("GenericArgumentsNotAllUnique", resourceCulture); + } + } + /// /// Looks up a localized string similar to Interpreter does not exist; analysis will not be available.. /// diff --git a/src/Analysis/Ast/Impl/Resources.resx b/src/Analysis/Ast/Impl/Resources.resx index b882f93f7..db7828c9f 100644 --- a/src/Analysis/Ast/Impl/Resources.resx +++ b/src/Analysis/Ast/Impl/Resources.resx @@ -192,4 +192,10 @@ Explicit return in __init__ - \ No newline at end of file + + Arguments to Generic must all be type parameters. + + + Arguments to Generic must all be unique. + + diff --git a/src/Analysis/Ast/Impl/Resources.resx.orig b/src/Analysis/Ast/Impl/Resources.resx.orig new file mode 100644 index 000000000..9abb6e07a --- /dev/null +++ b/src/Analysis/Ast/Impl/Resources.resx.orig @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + '{0}' may not be callable + + + object may not be callable + + + unresolved import '{0}' + + + Relative import '{0}' beyond top-level package + + + '{0}' used before definition + + + property of type {0} + + + property of unknown type + + + Parameter {0} already specified. + + + Parameter {0} is missing. + + + Positional arguments are not allowed after keyword argument. + + + Too many function arguments. + + + Too many positional arguments before '*' argument. + + + Unknown parameter name. + + + Analyzing in background, {0} items left... + + + Undefined variable: '{0}' + + + '{0}' is not defined in the global scope + + + '{0}' is not defined in non-local scopes + + + An exception occured while discovering search paths; analysis will not be available. + + + Interpreter does not exist; analysis will not be available. + + + Analysis cache path: {0} + + + Environment variable '{0}' is not set, using the default cache location instead. + + + Path '{0}' is not rooted, using the default cache location instead. + + + Unable to determine analysis cache path. Using default '{0}'. + + + Unable to determine analysis cache path. Exception: {0}. Using default '{1}'. + +<<<<<<< HEAD + + Explicit return in __init__ +======= + + Arguments to Generic must all be type parameters. + + + Arguments to Generic must all be unique. +>>>>>>> Adding diagnostic message for improperly using Generic + + \ No newline at end of file diff --git a/src/Analysis/Ast/Test/LintGenericTests.cs b/src/Analysis/Ast/Test/LintGenericTests.cs new file mode 100644 index 000000000..e6dc6a889 --- /dev/null +++ b/src/Analysis/Ast/Test/LintGenericTests.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NSubstitute; +using TestUtilities; + +namespace Microsoft.Python.Analysis.Tests { + + [TestClass] + public class LintGenericTests : AnalysisTestBase { + + public const string GenericSetup = @"from typing import Generic, TypeVar +T = TypeVar('T', int, str) +T1 = TypeVar('T1', int, str) +"; + + public TestContext TestContext { get; set; } + + [TestInitialize] + public void TestInitialize() + => TestEnvironmentImpl.TestInitialize($"{TestContext.FullyQualifiedTestClassName}.{TestContext.TestName}"); + + [TestCleanup] + public void Cleanup() => TestEnvironmentImpl.TestCleanup(); + + [DataRow(GenericSetup + @" +class Map(Generic[T, str]): + def hello(): + pass +")] + [DataRow(GenericSetup + @" +class Map(Generic[T, T1, int]): + def hello(): + pass +")] + [DataRow(GenericSetup + @" +class Map(Generic[T, str, int, T1]): + def hello(): + pass +")] + [DataTestMethod, Priority(0)] + public async Task GenericArgumentsNotAllTypeParameters(string code) { + var analysis = await GetAnalysisAsync(code); + analysis.Diagnostics.Should().HaveCount(1); + + var diagnostic = analysis.Diagnostics.ElementAt(0); + diagnostic.ErrorCode.Should().Be(Diagnostics.ErrorCodes.GenericArguments); + diagnostic.Message.Should().Be(Resources.GenericArgumentsNotAllTypeParameters); + } + + [TestMethod, Priority(0)] + public async Task GenericArgumentsDuplicate() { + var code = @" +from typing import Generic, TypeVar + +_X = TypeVar('_X', str, int) +_T = _X + +class Map(Generic[_T, _X]): + def hello(): + pass +"; + + var analysis = await GetAnalysisAsync(code); + analysis.Diagnostics.Should().HaveCount(1); + + var diagnostic = analysis.Diagnostics.ElementAt(0); + diagnostic.ErrorCode.Should().Be(Diagnostics.ErrorCodes.GenericArguments); + diagnostic.Message.Should().Be(Resources.GenericArgumentsNotAllUnique); + } + } +} From 49adedbc3620c7e734d7c77c1b9a8e93b938a51c Mon Sep 17 00:00:00 2001 From: Cameron Trando Date: Fri, 21 Jun 2019 15:48:58 -0700 Subject: [PATCH 02/10] Adding tests to make sure no diagnostics on valid uses of Generic --- src/Analysis/Ast/Test/LintGenericTests.cs | 59 ++++++++++++++++++++--- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/src/Analysis/Ast/Test/LintGenericTests.cs b/src/Analysis/Ast/Test/LintGenericTests.cs index e6dc6a889..c1c591c3a 100644 --- a/src/Analysis/Ast/Test/LintGenericTests.cs +++ b/src/Analysis/Ast/Test/LintGenericTests.cs @@ -52,19 +52,37 @@ public async Task GenericArgumentsNotAllTypeParameters(string code) { diagnostic.Message.Should().Be(Resources.GenericArgumentsNotAllTypeParameters); } - [TestMethod, Priority(0)] - public async Task GenericArgumentsDuplicate() { - var code = @" -from typing import Generic, TypeVar - + [DataRow(GenericSetup + @" _X = TypeVar('_X', str, int) _T = _X class Map(Generic[_T, _X]): def hello(): pass -"; +")] + [DataRow(GenericSetup + @" +_X = TypeVar('_X', str, int) +_T = _X + +class Map(Generic[_T, T, T1, _X]): + def hello(): + pass +")] + [DataRow(GenericSetup + @" +_X = TypeVar('_X', str, int) +_T = _X +class Map(Generic[_T,_T, T]): + def hello(): + pass +")] + [DataRow(GenericSetup + @" +class Map(Generic[T,T]): + def hello(): + pass +")] + [DataTestMethod, Priority(0)] + public async Task GenericArgumentsDuplicate(string code) { var analysis = await GetAnalysisAsync(code); analysis.Diagnostics.Should().HaveCount(1); @@ -72,5 +90,34 @@ def hello(): diagnostic.ErrorCode.Should().Be(Diagnostics.ErrorCodes.GenericArguments); diagnostic.Message.Should().Be(Resources.GenericArgumentsNotAllUnique); } + + [DataRow(GenericSetup + @" +_X = TypeVar('_X', str, int) + +class Map(Generic[_X, T]): + def hello(): + pass +")] + [DataRow(GenericSetup + @" +class Map(Generic[T1, T]): + def hello(): + pass +")] + [DataRow(GenericSetup + @" +class Map(Generic[T]): + def hello(): + pass +")] + [DataRow(GenericSetup + @" +_X = TypeVar('_X', str, int) +class Map(Generic[T,T1, _X]): + def hello(): + pass +")] + [DataTestMethod, Priority(0)] + public async Task GenericArgumentsNoDiagnosticOnValid(string code) { + var analysis = await GetAnalysisAsync(code); + analysis.Diagnostics.Should().HaveCount(0); + } } } From e150ff7b1de27beb90230f4f9f58a5cb538242c5 Mon Sep 17 00:00:00 2001 From: Cameron Trando Date: Mon, 24 Jun 2019 09:29:21 -0700 Subject: [PATCH 03/10] Adding error message on no arguments to Generic --- .../Evaluation/ExpressionEval.Generics.cs | 20 +++++++---- src/Analysis/Ast/Impl/Resources.Designer.cs | 17 ++++++--- src/Analysis/Ast/Impl/Resources.resx | 7 ++-- src/Analysis/Ast/Impl/Resources.resx.orig | 17 ++++++--- src/Analysis/Ast/Test/LintGenericTests.cs | 35 +++++++++++++------ 5 files changed, 70 insertions(+), 26 deletions(-) diff --git a/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs b/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs index 2b1db85a9..be8b9af58 100644 --- a/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs +++ b/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs @@ -64,16 +64,24 @@ private IMember GetValueFromGeneric(IMember target, Expression expr) { /// /// Returns whether the arguments to Generic are valid /// - private bool GenericClassParameterValid(IGenericTypeDefinition[] genericTypeArgs, IReadOnlyList indices, Expression expr) { - if (genericTypeArgs.Length == 0) { + private bool GenericClassParameterValid(IReadOnlyList genericTypeArgs, IReadOnlyList indices, Expression expr) { + // Cannot have Generic[] + if (genericTypeArgs.Count == 0) { + ReportDiagnostics(Module.Uri, new DiagnosticsEntry( + Resources.GenericTooFewArguments, + GetLocation(expr).Span, + ErrorCodes.GenericArguments, + Severity.Error, + DiagnosticSource.Analysis)); + return false; } // All arguments to Generic must be type parameters // e.g. Generic[T, str] throws a runtime error - if (genericTypeArgs.Length != indices.Count) { + if (genericTypeArgs.Count != indices.Count) { ReportDiagnostics(Module.Uri, new DiagnosticsEntry( - Resources.GenericArgumentsNotAllTypeParameters, + Resources.GenericNotAllTypeParameters, GetLocation(expr).Span, ErrorCodes.GenericArguments, Severity.Error, @@ -82,9 +90,9 @@ private bool GenericClassParameterValid(IGenericTypeDefinition[] genericTypeArgs } // All arguments to Generic must be distinct - if (genericTypeArgs.Distinct().Count() != genericTypeArgs.Length) { + if (genericTypeArgs.Distinct().Count() != genericTypeArgs.Count) { ReportDiagnostics(Module.Uri, new DiagnosticsEntry( - Resources.GenericArgumentsNotAllUnique, + Resources.GenericNotAllUnique, GetLocation(expr).Span, ErrorCodes.GenericArguments, Severity.Error, diff --git a/src/Analysis/Ast/Impl/Resources.Designer.cs b/src/Analysis/Ast/Impl/Resources.Designer.cs index d8333af03..727fca5b4 100644 --- a/src/Analysis/Ast/Impl/Resources.Designer.cs +++ b/src/Analysis/Ast/Impl/Resources.Designer.cs @@ -225,18 +225,27 @@ internal static string ExceptionGettingSearchPaths { /// /// Looks up a localized string similar to Arguments to Generic must all be type parameters.. /// - internal static string GenericArgumentsNotAllTypeParameters { + internal static string GenericNotAllTypeParameters { get { - return ResourceManager.GetString("GenericArgumentsNotAllTypeParameters", resourceCulture); + return ResourceManager.GetString("GenericNotAllTypeParameters", resourceCulture); } } /// /// Looks up a localized string similar to Arguments to Generic must all be unique.. /// - internal static string GenericArgumentsNotAllUnique { + internal static string GenericNotAllUnique { get { - return ResourceManager.GetString("GenericArgumentsNotAllUnique", resourceCulture); + return ResourceManager.GetString("GenericNotAllUnique", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Not enough arguments for Generic.. + /// + internal static string GenericTooFewArguments { + get { + return ResourceManager.GetString("GenericTooFewArguments", resourceCulture); } } diff --git a/src/Analysis/Ast/Impl/Resources.resx b/src/Analysis/Ast/Impl/Resources.resx index db7828c9f..7048086dc 100644 --- a/src/Analysis/Ast/Impl/Resources.resx +++ b/src/Analysis/Ast/Impl/Resources.resx @@ -192,10 +192,13 @@ Explicit return in __init__ - + Arguments to Generic must all be type parameters. - + Arguments to Generic must all be unique. + + Not enough arguments for Generic. + diff --git a/src/Analysis/Ast/Impl/Resources.resx.orig b/src/Analysis/Ast/Impl/Resources.resx.orig index 9abb6e07a..c7c8ae230 100644 --- a/src/Analysis/Ast/Impl/Resources.resx.orig +++ b/src/Analysis/Ast/Impl/Resources.resx.orig @@ -192,12 +192,21 @@ <<<<<<< HEAD Explicit return in __init__ -======= + +======= + +>>>>>>> Adding error message on no arguments to Generic Arguments to Generic must all be type parameters. - + Arguments to Generic must all be unique. ->>>>>>> Adding diagnostic message for improperly using Generic - \ No newline at end of file +<<<<<<< HEAD + +======= + + Not enough arguments for Generic. + + +>>>>>>> Adding error message on no arguments to Generic diff --git a/src/Analysis/Ast/Test/LintGenericTests.cs b/src/Analysis/Ast/Test/LintGenericTests.cs index c1c591c3a..4bd26b08a 100644 --- a/src/Analysis/Ast/Test/LintGenericTests.cs +++ b/src/Analysis/Ast/Test/LintGenericTests.cs @@ -1,11 +1,7 @@ -using System; -using System.Collections.Generic; +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Linq; -using System.Text; using System.Threading.Tasks; -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using NSubstitute; using TestUtilities; namespace Microsoft.Python.Analysis.Tests { @@ -27,6 +23,25 @@ public void TestInitialize() [TestCleanup] public void Cleanup() => TestEnvironmentImpl.TestCleanup(); + [DataRow(GenericSetup + @" +class Map(Generic[]): + def hello(): + pass +")] + [DataRow(GenericSetup + @" +G = Generic[] +")] + [DataTestMethod, Priority(0)] + public async Task GenericTooFewArguments(string code) { + var analysis = await GetAnalysisAsync(code); + analysis.Diagnostics.Should().HaveCount(1); + + var diagnostic = analysis.Diagnostics.ElementAt(0); + diagnostic.ErrorCode.Should().Be(Diagnostics.ErrorCodes.GenericArguments); + diagnostic.Message.Should().Be(Resources.GenericTooFewArguments); + } + + [DataRow(GenericSetup + @" class Map(Generic[T, str]): def hello(): @@ -43,13 +58,13 @@ def hello(): pass ")] [DataTestMethod, Priority(0)] - public async Task GenericArgumentsNotAllTypeParameters(string code) { + public async Task GenericNotALlTypParameters(string code) { var analysis = await GetAnalysisAsync(code); analysis.Diagnostics.Should().HaveCount(1); var diagnostic = analysis.Diagnostics.ElementAt(0); diagnostic.ErrorCode.Should().Be(Diagnostics.ErrorCodes.GenericArguments); - diagnostic.Message.Should().Be(Resources.GenericArgumentsNotAllTypeParameters); + diagnostic.Message.Should().Be(Resources.GenericNotAllTypeParameters); } [DataRow(GenericSetup + @" @@ -82,13 +97,13 @@ def hello(): pass ")] [DataTestMethod, Priority(0)] - public async Task GenericArgumentsDuplicate(string code) { + public async Task GenericDuplicateArguments(string code) { var analysis = await GetAnalysisAsync(code); analysis.Diagnostics.Should().HaveCount(1); var diagnostic = analysis.Diagnostics.ElementAt(0); diagnostic.ErrorCode.Should().Be(Diagnostics.ErrorCodes.GenericArguments); - diagnostic.Message.Should().Be(Resources.GenericArgumentsNotAllUnique); + diagnostic.Message.Should().Be(Resources.GenericNotAllUnique); } [DataRow(GenericSetup + @" From 1256e51f17e7e9c2915b33bd44463d5a14d2415c Mon Sep 17 00:00:00 2001 From: Cameron Trando Date: Mon, 24 Jun 2019 10:17:55 -0700 Subject: [PATCH 04/10] Revert "Adding error message on no arguments to Generic" This reverts commit 6dbc4aa629cb70b4a3282d3ddb77374412b2b200. --- .../Evaluation/ExpressionEval.Generics.cs | 20 ++++------- src/Analysis/Ast/Impl/Resources.Designer.cs | 17 +++------ src/Analysis/Ast/Impl/Resources.resx | 2 +- src/Analysis/Ast/Impl/Resources.resx.orig | 14 ++++---- src/Analysis/Ast/Test/LintGenericTests.cs | 35 ++++++------------- 5 files changed, 28 insertions(+), 60 deletions(-) diff --git a/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs b/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs index be8b9af58..2b1db85a9 100644 --- a/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs +++ b/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs @@ -64,24 +64,16 @@ private IMember GetValueFromGeneric(IMember target, Expression expr) { /// /// Returns whether the arguments to Generic are valid /// - private bool GenericClassParameterValid(IReadOnlyList genericTypeArgs, IReadOnlyList indices, Expression expr) { - // Cannot have Generic[] - if (genericTypeArgs.Count == 0) { - ReportDiagnostics(Module.Uri, new DiagnosticsEntry( - Resources.GenericTooFewArguments, - GetLocation(expr).Span, - ErrorCodes.GenericArguments, - Severity.Error, - DiagnosticSource.Analysis)); - + private bool GenericClassParameterValid(IGenericTypeDefinition[] genericTypeArgs, IReadOnlyList indices, Expression expr) { + if (genericTypeArgs.Length == 0) { return false; } // All arguments to Generic must be type parameters // e.g. Generic[T, str] throws a runtime error - if (genericTypeArgs.Count != indices.Count) { + if (genericTypeArgs.Length != indices.Count) { ReportDiagnostics(Module.Uri, new DiagnosticsEntry( - Resources.GenericNotAllTypeParameters, + Resources.GenericArgumentsNotAllTypeParameters, GetLocation(expr).Span, ErrorCodes.GenericArguments, Severity.Error, @@ -90,9 +82,9 @@ private bool GenericClassParameterValid(IReadOnlyList ge } // All arguments to Generic must be distinct - if (genericTypeArgs.Distinct().Count() != genericTypeArgs.Count) { + if (genericTypeArgs.Distinct().Count() != genericTypeArgs.Length) { ReportDiagnostics(Module.Uri, new DiagnosticsEntry( - Resources.GenericNotAllUnique, + Resources.GenericArgumentsNotAllUnique, GetLocation(expr).Span, ErrorCodes.GenericArguments, Severity.Error, diff --git a/src/Analysis/Ast/Impl/Resources.Designer.cs b/src/Analysis/Ast/Impl/Resources.Designer.cs index 727fca5b4..d8333af03 100644 --- a/src/Analysis/Ast/Impl/Resources.Designer.cs +++ b/src/Analysis/Ast/Impl/Resources.Designer.cs @@ -225,27 +225,18 @@ internal static string ExceptionGettingSearchPaths { /// /// Looks up a localized string similar to Arguments to Generic must all be type parameters.. /// - internal static string GenericNotAllTypeParameters { + internal static string GenericArgumentsNotAllTypeParameters { get { - return ResourceManager.GetString("GenericNotAllTypeParameters", resourceCulture); + return ResourceManager.GetString("GenericArgumentsNotAllTypeParameters", resourceCulture); } } /// /// Looks up a localized string similar to Arguments to Generic must all be unique.. /// - internal static string GenericNotAllUnique { + internal static string GenericArgumentsNotAllUnique { get { - return ResourceManager.GetString("GenericNotAllUnique", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Not enough arguments for Generic.. - /// - internal static string GenericTooFewArguments { - get { - return ResourceManager.GetString("GenericTooFewArguments", resourceCulture); + return ResourceManager.GetString("GenericArgumentsNotAllUnique", resourceCulture); } } diff --git a/src/Analysis/Ast/Impl/Resources.resx b/src/Analysis/Ast/Impl/Resources.resx index 7048086dc..cbb135ee3 100644 --- a/src/Analysis/Ast/Impl/Resources.resx +++ b/src/Analysis/Ast/Impl/Resources.resx @@ -195,7 +195,7 @@ Arguments to Generic must all be type parameters. - + Arguments to Generic must all be unique. diff --git a/src/Analysis/Ast/Impl/Resources.resx.orig b/src/Analysis/Ast/Impl/Resources.resx.orig index c7c8ae230..1184cd278 100644 --- a/src/Analysis/Ast/Impl/Resources.resx.orig +++ b/src/Analysis/Ast/Impl/Resources.resx.orig @@ -193,20 +193,20 @@ Explicit return in __init__ - -======= ->>>>>>> Adding error message on no arguments to Generic +======= + +>>>>>>> Revert "Adding error message on no arguments to Generic" Arguments to Generic must all be type parameters. - + Arguments to Generic must all be unique. <<<<<<< HEAD - -======= Not enough arguments for Generic. ->>>>>>> Adding error message on no arguments to Generic +======= + +>>>>>>> Revert "Adding error message on no arguments to Generic" diff --git a/src/Analysis/Ast/Test/LintGenericTests.cs b/src/Analysis/Ast/Test/LintGenericTests.cs index 4bd26b08a..c1c591c3a 100644 --- a/src/Analysis/Ast/Test/LintGenericTests.cs +++ b/src/Analysis/Ast/Test/LintGenericTests.cs @@ -1,7 +1,11 @@ -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; using System.Linq; +using System.Text; using System.Threading.Tasks; +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NSubstitute; using TestUtilities; namespace Microsoft.Python.Analysis.Tests { @@ -23,25 +27,6 @@ public void TestInitialize() [TestCleanup] public void Cleanup() => TestEnvironmentImpl.TestCleanup(); - [DataRow(GenericSetup + @" -class Map(Generic[]): - def hello(): - pass -")] - [DataRow(GenericSetup + @" -G = Generic[] -")] - [DataTestMethod, Priority(0)] - public async Task GenericTooFewArguments(string code) { - var analysis = await GetAnalysisAsync(code); - analysis.Diagnostics.Should().HaveCount(1); - - var diagnostic = analysis.Diagnostics.ElementAt(0); - diagnostic.ErrorCode.Should().Be(Diagnostics.ErrorCodes.GenericArguments); - diagnostic.Message.Should().Be(Resources.GenericTooFewArguments); - } - - [DataRow(GenericSetup + @" class Map(Generic[T, str]): def hello(): @@ -58,13 +43,13 @@ def hello(): pass ")] [DataTestMethod, Priority(0)] - public async Task GenericNotALlTypParameters(string code) { + public async Task GenericArgumentsNotAllTypeParameters(string code) { var analysis = await GetAnalysisAsync(code); analysis.Diagnostics.Should().HaveCount(1); var diagnostic = analysis.Diagnostics.ElementAt(0); diagnostic.ErrorCode.Should().Be(Diagnostics.ErrorCodes.GenericArguments); - diagnostic.Message.Should().Be(Resources.GenericNotAllTypeParameters); + diagnostic.Message.Should().Be(Resources.GenericArgumentsNotAllTypeParameters); } [DataRow(GenericSetup + @" @@ -97,13 +82,13 @@ def hello(): pass ")] [DataTestMethod, Priority(0)] - public async Task GenericDuplicateArguments(string code) { + public async Task GenericArgumentsDuplicate(string code) { var analysis = await GetAnalysisAsync(code); analysis.Diagnostics.Should().HaveCount(1); var diagnostic = analysis.Diagnostics.ElementAt(0); diagnostic.ErrorCode.Should().Be(Diagnostics.ErrorCodes.GenericArguments); - diagnostic.Message.Should().Be(Resources.GenericNotAllUnique); + diagnostic.Message.Should().Be(Resources.GenericArgumentsNotAllUnique); } [DataRow(GenericSetup + @" From 0fbd6c7cf8cca458012bf0e575334b1ffd8e641d Mon Sep 17 00:00:00 2001 From: Cameron Trando Date: Mon, 24 Jun 2019 10:26:23 -0700 Subject: [PATCH 05/10] Case of Generic[int] where there are no generic type parameters now will have a diagnostic message, minor name changes --- .../Evaluation/ExpressionEval.Generics.cs | 14 +++++------- src/Analysis/Ast/Impl/Resources.Designer.cs | 8 +++---- src/Analysis/Ast/Impl/Resources.resx | 2 +- src/Analysis/Ast/Impl/Resources.resx.orig | 11 +++------- src/Analysis/Ast/Test/LintGenericTests.cs | 22 ++++++++++++++----- 5 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs b/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs index 2b1db85a9..a5cc1502a 100644 --- a/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs +++ b/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs @@ -64,16 +64,12 @@ private IMember GetValueFromGeneric(IMember target, Expression expr) { /// /// Returns whether the arguments to Generic are valid /// - private bool GenericClassParameterValid(IGenericTypeDefinition[] genericTypeArgs, IReadOnlyList indices, Expression expr) { - if (genericTypeArgs.Length == 0) { - return false; - } - + private bool GenericClassParameterValid(IReadOnlyList genericTypeArgs, IReadOnlyList args, Expression expr) { // All arguments to Generic must be type parameters // e.g. Generic[T, str] throws a runtime error - if (genericTypeArgs.Length != indices.Count) { + if (genericTypeArgs.Count != args.Count) { ReportDiagnostics(Module.Uri, new DiagnosticsEntry( - Resources.GenericArgumentsNotAllTypeParameters, + Resources.GenericNotAllTypeParameters, GetLocation(expr).Span, ErrorCodes.GenericArguments, Severity.Error, @@ -82,9 +78,9 @@ private bool GenericClassParameterValid(IGenericTypeDefinition[] genericTypeArgs } // All arguments to Generic must be distinct - if (genericTypeArgs.Distinct().Count() != genericTypeArgs.Length) { + if (genericTypeArgs.Distinct().Count() != genericTypeArgs.Count) { ReportDiagnostics(Module.Uri, new DiagnosticsEntry( - Resources.GenericArgumentsNotAllUnique, + Resources.GenericNotAllUnique, GetLocation(expr).Span, ErrorCodes.GenericArguments, Severity.Error, diff --git a/src/Analysis/Ast/Impl/Resources.Designer.cs b/src/Analysis/Ast/Impl/Resources.Designer.cs index d8333af03..df406b0eb 100644 --- a/src/Analysis/Ast/Impl/Resources.Designer.cs +++ b/src/Analysis/Ast/Impl/Resources.Designer.cs @@ -225,18 +225,18 @@ internal static string ExceptionGettingSearchPaths { /// /// Looks up a localized string similar to Arguments to Generic must all be type parameters.. /// - internal static string GenericArgumentsNotAllTypeParameters { + internal static string GenericNotAllTypeParameters { get { - return ResourceManager.GetString("GenericArgumentsNotAllTypeParameters", resourceCulture); + return ResourceManager.GetString("GenericNotAllTypeParameters", resourceCulture); } } /// /// Looks up a localized string similar to Arguments to Generic must all be unique.. /// - internal static string GenericArgumentsNotAllUnique { + internal static string GenericNotAllUnique { get { - return ResourceManager.GetString("GenericArgumentsNotAllUnique", resourceCulture); + return ResourceManager.GetString("GenericNotAllUnique", resourceCulture); } } diff --git a/src/Analysis/Ast/Impl/Resources.resx b/src/Analysis/Ast/Impl/Resources.resx index cbb135ee3..7048086dc 100644 --- a/src/Analysis/Ast/Impl/Resources.resx +++ b/src/Analysis/Ast/Impl/Resources.resx @@ -195,7 +195,7 @@ Arguments to Generic must all be type parameters. - + Arguments to Generic must all be unique. diff --git a/src/Analysis/Ast/Impl/Resources.resx.orig b/src/Analysis/Ast/Impl/Resources.resx.orig index 1184cd278..d40dd7da7 100644 --- a/src/Analysis/Ast/Impl/Resources.resx.orig +++ b/src/Analysis/Ast/Impl/Resources.resx.orig @@ -193,20 +193,15 @@ Explicit return in __init__ - ======= - ->>>>>>> Revert "Adding error message on no arguments to Generic" +>>>>>>> Case of Generic[int] where there are no generic type parameters now will have a diagnostic message, minor name changes + Arguments to Generic must all be type parameters. - + Arguments to Generic must all be unique. -<<<<<<< HEAD Not enough arguments for Generic. -======= - ->>>>>>> Revert "Adding error message on no arguments to Generic" diff --git a/src/Analysis/Ast/Test/LintGenericTests.cs b/src/Analysis/Ast/Test/LintGenericTests.cs index c1c591c3a..92f054516 100644 --- a/src/Analysis/Ast/Test/LintGenericTests.cs +++ b/src/Analysis/Ast/Test/LintGenericTests.cs @@ -42,14 +42,26 @@ class Map(Generic[T, str, int, T1]): def hello(): pass ")] + [DataRow(GenericSetup + @" +class Map(Generic[str, int]): + def hello(): + pass +")] + [DataRow(GenericSetup + @" +class Map(Generic[str]): + def hello(): + pass +")] + + [DataTestMethod, Priority(0)] - public async Task GenericArgumentsNotAllTypeParameters(string code) { + public async Task GenericNotAllTypeParameters(string code) { var analysis = await GetAnalysisAsync(code); analysis.Diagnostics.Should().HaveCount(1); var diagnostic = analysis.Diagnostics.ElementAt(0); diagnostic.ErrorCode.Should().Be(Diagnostics.ErrorCodes.GenericArguments); - diagnostic.Message.Should().Be(Resources.GenericArgumentsNotAllTypeParameters); + diagnostic.Message.Should().Be(Resources.GenericNotAllTypeParameters); } [DataRow(GenericSetup + @" @@ -82,16 +94,16 @@ def hello(): pass ")] [DataTestMethod, Priority(0)] - public async Task GenericArgumentsDuplicate(string code) { + public async Task GenericDuplicateArguments(string code) { var analysis = await GetAnalysisAsync(code); analysis.Diagnostics.Should().HaveCount(1); var diagnostic = analysis.Diagnostics.ElementAt(0); diagnostic.ErrorCode.Should().Be(Diagnostics.ErrorCodes.GenericArguments); - diagnostic.Message.Should().Be(Resources.GenericArgumentsNotAllUnique); + diagnostic.Message.Should().Be(Resources.GenericNotAllUnique); } - [DataRow(GenericSetup + @" + [DataRow(GenericSetup + @" _X = TypeVar('_X', str, int) class Map(Generic[_X, T]): From 1650173f82ac08636635f62954312ceef535374b Mon Sep 17 00:00:00 2001 From: Cameron Trando Date: Mon, 1 Jul 2019 10:42:10 -0700 Subject: [PATCH 06/10] Prefixing error code with typing --- .../Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs | 4 ++-- src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs | 2 +- src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs.orig | 5 +++-- src/Analysis/Ast/Test/LintGenericTests.cs | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs b/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs index a5cc1502a..b36242ba2 100644 --- a/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs +++ b/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs @@ -71,7 +71,7 @@ private bool GenericClassParameterValid(IReadOnlyList ge ReportDiagnostics(Module.Uri, new DiagnosticsEntry( Resources.GenericNotAllTypeParameters, GetLocation(expr).Span, - ErrorCodes.GenericArguments, + ErrorCodes.TypingGenericArguments, Severity.Error, DiagnosticSource.Analysis)); return false; @@ -82,7 +82,7 @@ private bool GenericClassParameterValid(IReadOnlyList ge ReportDiagnostics(Module.Uri, new DiagnosticsEntry( Resources.GenericNotAllUnique, GetLocation(expr).Span, - ErrorCodes.GenericArguments, + ErrorCodes.TypingGenericArguments, Severity.Error, DiagnosticSource.Analysis)); return false; diff --git a/src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs b/src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs index 7996edd80..fd6d5f0c9 100644 --- a/src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs +++ b/src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs @@ -26,6 +26,6 @@ public static class ErrorCodes { public const string VariableNotDefinedGlobally= "variable-not-defined-globally"; public const string VariableNotDefinedNonLocal = "variable-not-defined-nonlocal"; public const string ReturnInInit = "return-in-init"; - public const string GenericArguments = "generic-arguments"; + public const string TypingGenericArguments = "typing-generic-arguments"; } } diff --git a/src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs.orig b/src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs.orig index 31347af00..e6df2249f 100644 --- a/src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs.orig +++ b/src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs.orig @@ -27,8 +27,9 @@ namespace Microsoft.Python.Analysis.Diagnostics { public const string VariableNotDefinedNonLocal = "variable-not-defined-nonlocal"; <<<<<<< HEAD public const string ReturnInInit = "return-in-init"; -======= public const string GenericArguments = "generic-arguments"; ->>>>>>> Adding diagnostic message for improperly using Generic +======= + public const string TypingGenericArguments = "typing-generic-arguments"; +>>>>>>> Prefixing error code with typing } } diff --git a/src/Analysis/Ast/Test/LintGenericTests.cs b/src/Analysis/Ast/Test/LintGenericTests.cs index 92f054516..b0f719194 100644 --- a/src/Analysis/Ast/Test/LintGenericTests.cs +++ b/src/Analysis/Ast/Test/LintGenericTests.cs @@ -60,7 +60,7 @@ public async Task GenericNotAllTypeParameters(string code) { analysis.Diagnostics.Should().HaveCount(1); var diagnostic = analysis.Diagnostics.ElementAt(0); - diagnostic.ErrorCode.Should().Be(Diagnostics.ErrorCodes.GenericArguments); + diagnostic.ErrorCode.Should().Be(Diagnostics.ErrorCodes.TypingGenericArguments); diagnostic.Message.Should().Be(Resources.GenericNotAllTypeParameters); } @@ -99,7 +99,7 @@ public async Task GenericDuplicateArguments(string code) { analysis.Diagnostics.Should().HaveCount(1); var diagnostic = analysis.Diagnostics.ElementAt(0); - diagnostic.ErrorCode.Should().Be(Diagnostics.ErrorCodes.GenericArguments); + diagnostic.ErrorCode.Should().Be(Diagnostics.ErrorCodes.TypingGenericArguments); diagnostic.Message.Should().Be(Resources.GenericNotAllUnique); } From 3a63bb813c479115e5f5782711b5784e21b91976 Mon Sep 17 00:00:00 2001 From: Cameron Trando Date: Tue, 2 Jul 2019 10:23:56 -0700 Subject: [PATCH 07/10] Adding span check in test --- src/Analysis/Ast/Test/LintGenericTests.cs | 130 +++++++--------------- 1 file changed, 41 insertions(+), 89 deletions(-) diff --git a/src/Analysis/Ast/Test/LintGenericTests.cs b/src/Analysis/Ast/Test/LintGenericTests.cs index b0f719194..ef311c801 100644 --- a/src/Analysis/Ast/Test/LintGenericTests.cs +++ b/src/Analysis/Ast/Test/LintGenericTests.cs @@ -1,21 +1,25 @@ -using System; -using System.Collections.Generic; +using FluentAssertions; +using Microsoft.Python.Analysis.Tests.FluentAssertions; +using Microsoft.Python.Parsing.Tests; +using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Linq; -using System.Text; +using System.Runtime.InteropServices.ComTypes; using System.Threading.Tasks; -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using NSubstitute; using TestUtilities; + namespace Microsoft.Python.Analysis.Tests { [TestClass] public class LintGenericTests : AnalysisTestBase { - public const string GenericSetup = @"from typing import Generic, TypeVar + public const string GenericSetup = @" +from typing import Generic, TypeVar T = TypeVar('T', int, str) T1 = TypeVar('T1', int, str) + +_X = TypeVar('_X', str, int) +_T = _X "; public TestContext TestContext { get; set; } @@ -27,107 +31,55 @@ public void TestInitialize() [TestCleanup] public void Cleanup() => TestEnvironmentImpl.TestCleanup(); - [DataRow(GenericSetup + @" -class Map(Generic[T, str]): - def hello(): - pass -")] - [DataRow(GenericSetup + @" -class Map(Generic[T, T1, int]): - def hello(): - pass -")] - [DataRow(GenericSetup + @" -class Map(Generic[T, str, int, T1]): - def hello(): - pass -")] - [DataRow(GenericSetup + @" -class Map(Generic[str, int]): - def hello(): - pass -")] - [DataRow(GenericSetup + @" -class Map(Generic[str]): - def hello(): - pass -")] - - + [DataRow("x = Generic[T, str]")] + [DataRow("x = Generic[T, T1, int]")] + [DataRow("x = Generic[T, str, int, T1]")] + [DataRow("x = Generic[str, int]")] + [DataRow("x = Generic[str]")] [DataTestMethod, Priority(0)] - public async Task GenericNotAllTypeParameters(string code) { + public async Task GenericNotAllTypeParameters(string decl) { + string code = GenericSetup + decl; + var analysis = await GetAnalysisAsync(code); analysis.Diagnostics.Should().HaveCount(1); var diagnostic = analysis.Diagnostics.ElementAt(0); + var start = decl.IndexOf("Generic") + 1; + // adding 1 because SourceSpan.End is exclusive and another 1 because SourceSpan is 1-indexed + var end = decl.IndexOf("]", start) + 2; + + diagnostic.SourceSpan.Should().Be(8, start, 8, end); diagnostic.ErrorCode.Should().Be(Diagnostics.ErrorCodes.TypingGenericArguments); diagnostic.Message.Should().Be(Resources.GenericNotAllTypeParameters); } - [DataRow(GenericSetup + @" -_X = TypeVar('_X', str, int) -_T = _X - -class Map(Generic[_T, _X]): - def hello(): - pass -")] - [DataRow(GenericSetup + @" -_X = TypeVar('_X', str, int) -_T = _X - -class Map(Generic[_T, T, T1, _X]): - def hello(): - pass -")] - [DataRow(GenericSetup + @" -_X = TypeVar('_X', str, int) -_T = _X - -class Map(Generic[_T,_T, T]): - def hello(): - pass -")] - [DataRow(GenericSetup + @" -class Map(Generic[T,T]): - def hello(): - pass -")] + [DataRow("x = Generic[_T, _X]")] + [DataRow("x = Generic[_T, T, T1, _X]")] + [DataRow("x = Generic[_T,_T, T]")] + [DataRow("x = Generic[T,T]")] [DataTestMethod, Priority(0)] - public async Task GenericDuplicateArguments(string code) { + public async Task GenericDuplicateArguments(string decl) { + string code = GenericSetup + decl; var analysis = await GetAnalysisAsync(code); analysis.Diagnostics.Should().HaveCount(1); var diagnostic = analysis.Diagnostics.ElementAt(0); + var start = decl.IndexOf("Generic") + 1; + // adding 1 because SourceSpan.End is exclusive and another 1 because SourceSpan is 1-indexed + var end = decl.IndexOf("]", start) + 2; + diagnostic.SourceSpan.Should().Be(8, start, 8, end); + diagnostic.ErrorCode.Should().Be(Diagnostics.ErrorCodes.TypingGenericArguments); diagnostic.Message.Should().Be(Resources.GenericNotAllUnique); } - [DataRow(GenericSetup + @" -_X = TypeVar('_X', str, int) - -class Map(Generic[_X, T]): - def hello(): - pass -")] - [DataRow(GenericSetup + @" -class Map(Generic[T1, T]): - def hello(): - pass -")] - [DataRow(GenericSetup + @" -class Map(Generic[T]): - def hello(): - pass -")] - [DataRow(GenericSetup + @" -_X = TypeVar('_X', str, int) -class Map(Generic[T,T1, _X]): - def hello(): - pass -")] + [DataRow("x = Generic[_X, T]")] + [DataRow("x = Generic[T1, T]")] + [DataRow("x = Generic[T]")] + [DataRow("x = Generic[T,T1, _X]")] [DataTestMethod, Priority(0)] - public async Task GenericArgumentsNoDiagnosticOnValid(string code) { + public async Task GenericArgumentsNoDiagnosticOnValid(string decl) { + string code = GenericSetup + decl; var analysis = await GetAnalysisAsync(code); analysis.Diagnostics.Should().HaveCount(0); } From 441532ac2acfab1fb2e5d4bbb062a205690b463a Mon Sep 17 00:00:00 2001 From: Cameron Trando Date: Tue, 2 Jul 2019 10:31:11 -0700 Subject: [PATCH 08/10] Fixing imports in tests --- src/Analysis/Ast/Test/LintGenericTests.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Analysis/Ast/Test/LintGenericTests.cs b/src/Analysis/Ast/Test/LintGenericTests.cs index ef311c801..86f09faba 100644 --- a/src/Analysis/Ast/Test/LintGenericTests.cs +++ b/src/Analysis/Ast/Test/LintGenericTests.cs @@ -1,10 +1,9 @@ -using FluentAssertions; +using System.Linq; +using System.Threading.Tasks; +using FluentAssertions; using Microsoft.Python.Analysis.Tests.FluentAssertions; using Microsoft.Python.Parsing.Tests; using Microsoft.VisualStudio.TestTools.UnitTesting; -using System.Linq; -using System.Runtime.InteropServices.ComTypes; -using System.Threading.Tasks; using TestUtilities; From 6735762df453cf6b7690813e4b5f029f86ded711 Mon Sep 17 00:00:00 2001 From: Cameron Trando Date: Tue, 2 Jul 2019 10:50:19 -0700 Subject: [PATCH 09/10] Removing generic error msg --- src/Analysis/Ast/Impl/Resources.resx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Analysis/Ast/Impl/Resources.resx b/src/Analysis/Ast/Impl/Resources.resx index 7048086dc..e9a661561 100644 --- a/src/Analysis/Ast/Impl/Resources.resx +++ b/src/Analysis/Ast/Impl/Resources.resx @@ -198,7 +198,4 @@ Arguments to Generic must all be unique. - - Not enough arguments for Generic. - - + \ No newline at end of file From 83e4aff7af004241e71bc7fa89305d4624ee4106 Mon Sep 17 00:00:00 2001 From: Cameron Trando Date: Tue, 2 Jul 2019 10:53:21 -0700 Subject: [PATCH 10/10] Removing .orig files --- .../ExpressionEval.Generics.cs.orig | 241 ------------------ .../Ast/Impl/Diagnostics/ErrorCodes.cs.orig | 35 --- src/Analysis/Ast/Impl/Resources.resx.orig | 207 --------------- 3 files changed, 483 deletions(-) delete mode 100644 src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs.orig delete mode 100644 src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs.orig delete mode 100644 src/Analysis/Ast/Impl/Resources.resx.orig diff --git a/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs.orig b/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs.orig deleted file mode 100644 index c52c15b8c..000000000 --- a/src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs.orig +++ /dev/null @@ -1,241 +0,0 @@ -// 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 System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.Python.Analysis.Diagnostics; -using Microsoft.Python.Analysis.Specializations.Typing; -using Microsoft.Python.Analysis.Specializations.Typing.Types; -using Microsoft.Python.Analysis.Types; -using Microsoft.Python.Analysis.Values; -using Microsoft.Python.Core; -using Microsoft.Python.Core.Text; -using Microsoft.Python.Parsing; -using Microsoft.Python.Parsing.Ast; -using ErrorCodes = Microsoft.Python.Analysis.Diagnostics.ErrorCodes; - -namespace Microsoft.Python.Analysis.Analyzer.Evaluation { - internal sealed partial class ExpressionEval { - /// - /// Creates specific type from expression that involves generic type - /// and the specific type arguments, such as Generic[T] or constructor - /// of a generic class. - /// - private IMember GetValueFromGeneric(IMember target, Expression expr) { - if (!(target is PythonClassType c && c.IsGeneric()) && !(target is IGenericType)) { - return null; - } - - using (OpenScope(target.GetPythonType()?.DeclaringModule, GetScope(target), out _)) { - // Try generics - // Evaluate index to check if the result is a generic parameter. - // If it is, then this is a declaration expression such as Generic[T] - // rather than specific type instantiation as in List[str]. - switch (expr) { - // Indexing returns type as from A[int] - case IndexExpression indexExpr when target is IGenericType gt: - // Generic[T1, T2, ...] - var indices = EvaluateIndex(indexExpr); - return CreateSpecificTypeFromIndex(gt, indices, expr); - - case CallExpression callExpr when target is PythonClassType c1: - // Alternative instantiation: - // class A(Generic[T]): ... - // x = A(1234) - var arguments = EvaluateCallArgs(callExpr).ToArray(); - return CreateClassInstance(c1, arguments, callExpr); - } - } - return null; - } - - /// - /// Returns whether the arguments to Generic are valid - /// - private bool GenericClassParameterValid(IGenericTypeDefinition[] genericTypeArgs, IReadOnlyList indices, Expression expr) { - if (genericTypeArgs.Length == 0) { - return false; - } - - // All arguments to Generic must be type parameters - // e.g. Generic[T, str] throws a runtime error - if (genericTypeArgs.Length != indices.Count) { - ReportDiagnostics(Module.Uri, new DiagnosticsEntry( - Resources.GenericArgumentsNotAllTypeParameters, - GetLocation(expr).Span, - ErrorCodes.GenericArguments, - Severity.Error, - DiagnosticSource.Analysis)); - return false; - } - - // All arguments to Generic must be distinct - if (genericTypeArgs.Distinct().Count() != genericTypeArgs.Length) { - ReportDiagnostics(Module.Uri, new DiagnosticsEntry( - Resources.GenericArgumentsNotAllUnique, - GetLocation(expr).Span, - ErrorCodes.GenericArguments, - Severity.Error, - DiagnosticSource.Analysis)); - return false; - } - - return true; - } - - /// - /// Given generic type and list of arguments in the expression like - /// Generic[T1, T2, ...] or List[str] creates generic class base - /// (if the former) on specific type (if the latter). - /// - private IMember CreateSpecificTypeFromIndex(IGenericType gt, IReadOnlyList args, Expression expr) { - var genericTypeArgs = args.OfType().ToArray(); - - if (gt.Name.EqualsOrdinal("Generic")) { - if (!GenericClassParameterValid(genericTypeArgs, args, expr)) { - return UnknownType; - } - - // Generic[T1, T2, ...] expression. Create generic base for the class. - return new GenericClassParameter(genericTypeArgs, Module); - } - - // For other types just use supplied arguments -<<<<<<< HEAD - if (indices.Count > 0) { - return gt.CreateSpecificType(new ArgumentSet(indices, expr, this)); -======= - if (args.Count > 0) { - return gt.CreateSpecificType(new ArgumentSet(args)); ->>>>>>> Adding diagnostic message for improperly using Generic - } - - return UnknownType; - } - - private IReadOnlyList EvaluateIndex(IndexExpression expr) { - var indices = new List(); - if (expr.Index is TupleExpression tex) { - foreach (var item in tex.Items) { - var e = GetValueFromExpression(item); - indices.Add(e); - } - } else { - var index = GetValueFromExpression(expr.Index); - indices.Add(index ?? UnknownType); - } - return indices; - } - - private IReadOnlyList EvaluateCallArgs(CallExpression expr) { - var indices = new List(); - foreach (var e in expr.Args.Select(a => a.Expression)) { - var value = GetValueFromExpression(e) ?? UnknownType; - indices.Add(value); - } - return indices; - } - - /// - /// Given generic class type and the passed constructor arguments - /// creates specific type and instance of the type. Attempts to match - /// supplied arguments to either __init__ signature or to the - /// list of generic definitions in Generic[T1, T2, ...]. - /// - private IMember CreateClassInstance(PythonClassType cls, IReadOnlyList constructorArguments, CallExpression callExpr) { - // Look at the constructor arguments and create argument set - // based on the __init__ definition. - var initFunc = cls.GetMember(@"__init__") as IPythonFunctionType; - var initOverload = initFunc?.DeclaringType == cls ? initFunc.Overloads.FirstOrDefault() : null; - - var argSet = initOverload != null - ? new ArgumentSet(initFunc, 0, null, callExpr, this) - : new ArgumentSet(constructorArguments, callExpr, this); - - argSet.Evaluate(); - var specificType = cls.CreateSpecificType(argSet); - return new PythonInstance(specificType); - } - - private ScopeStatement GetScope(IMember m) { - switch (m.GetPythonType()) { - case IPythonClassType ct: - return ct.ClassDefinition; - case IPythonFunctionType ct: - return ct.FunctionDefinition; - } - return null; - } - - public static IReadOnlyList GetTypeArgumentsFromParameters(IPythonFunctionOverload o, IArgumentSet args) { - if (o.Parameters.Any(p => p.IsGeneric)) { - // Declaring class is not generic, but the function is and arguments - // should provide actual specific types. - // TODO: handle keyword and dict args - var list = new List(); - for (var i = 0; i < Math.Min(o.Parameters.Count, args.Arguments.Count); i++) { - if (o.Parameters[i].IsGeneric) { - list.AddRange(GetSpecificTypeFromArgumentValue(args.Arguments[i].Value)); - } - } - return list; - } - return null; - } - - /// - /// Given argument attempts to extract specific types for the function generic - /// parameter(s). Handles common cases such as dictionary, list and tuple. - /// Typically used on a value that is being passed to the function in place - /// of the generic parameter. - /// - /// - /// Consider 'def func(x: Mapping[K, V]) -> K: ...' - /// - private static IReadOnlyList GetSpecificTypeFromArgumentValue(object argumentValue) { - var specificTypes = new List(); - switch (argumentValue) { - case IPythonDictionary dict: - var keyType = dict.Keys.FirstOrDefault()?.GetPythonType(); - var valueType = dict.Values.FirstOrDefault()?.GetPythonType(); - if (!keyType.IsUnknown()) { - specificTypes.Add(keyType); - } - if (!valueType.IsUnknown()) { - specificTypes.Add(valueType); - } - break; - case IPythonCollection coll: - specificTypes.AddRange(coll.Contents.Select(m => m.GetPythonType())); - break; - case IPythonIterable iter: - var itemType = iter.GetIterator().Next.GetPythonType(); - if (!itemType.IsUnknown()) { - specificTypes.Add(itemType); - } else if (argumentValue is IPythonInstance inst) { - specificTypes.Add(inst.GetPythonType()); - } - break; - case IMember m: - if (!m.IsUnknown()) { - specificTypes.Add(m.GetPythonType()); - } - break; - } - return specificTypes; - } - } -} diff --git a/src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs.orig b/src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs.orig deleted file mode 100644 index e6df2249f..000000000 --- a/src/Analysis/Ast/Impl/Diagnostics/ErrorCodes.cs.orig +++ /dev/null @@ -1,35 +0,0 @@ -// 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. - -namespace Microsoft.Python.Analysis.Diagnostics { - public static class ErrorCodes { - public const string TooManyFunctionArguments = "too-many-function-arguments"; - public const string TooManyPositionalArgumentsBeforeStar = "too-many-positional-arguments-before-star"; - public const string PositionalArgumentAfterKeyword = "positional-argument-after-keyword"; - public const string UnknownParameterName = "unknown-parameter-name"; - public const string ParameterAlreadySpecified = "parameter-already-specified"; - public const string ParameterMissing = "parameter-missing"; - public const string UnresolvedImport = "unresolved-import"; - public const string UndefinedVariable = "undefined-variable"; - public const string VariableNotDefinedGlobally= "variable-not-defined-globally"; - public const string VariableNotDefinedNonLocal = "variable-not-defined-nonlocal"; -<<<<<<< HEAD - public const string ReturnInInit = "return-in-init"; - public const string GenericArguments = "generic-arguments"; -======= - public const string TypingGenericArguments = "typing-generic-arguments"; ->>>>>>> Prefixing error code with typing - } -} diff --git a/src/Analysis/Ast/Impl/Resources.resx.orig b/src/Analysis/Ast/Impl/Resources.resx.orig deleted file mode 100644 index d40dd7da7..000000000 --- a/src/Analysis/Ast/Impl/Resources.resx.orig +++ /dev/null @@ -1,207 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - '{0}' may not be callable - - - object may not be callable - - - unresolved import '{0}' - - - Relative import '{0}' beyond top-level package - - - '{0}' used before definition - - - property of type {0} - - - property of unknown type - - - Parameter {0} already specified. - - - Parameter {0} is missing. - - - Positional arguments are not allowed after keyword argument. - - - Too many function arguments. - - - Too many positional arguments before '*' argument. - - - Unknown parameter name. - - - Analyzing in background, {0} items left... - - - Undefined variable: '{0}' - - - '{0}' is not defined in the global scope - - - '{0}' is not defined in non-local scopes - - - An exception occured while discovering search paths; analysis will not be available. - - - Interpreter does not exist; analysis will not be available. - - - Analysis cache path: {0} - - - Environment variable '{0}' is not set, using the default cache location instead. - - - Path '{0}' is not rooted, using the default cache location instead. - - - Unable to determine analysis cache path. Using default '{0}'. - - - Unable to determine analysis cache path. Exception: {0}. Using default '{1}'. - -<<<<<<< HEAD - - Explicit return in __init__ - -======= ->>>>>>> Case of Generic[int] where there are no generic type parameters now will have a diagnostic message, minor name changes - - Arguments to Generic must all be type parameters. - - - Arguments to Generic must all be unique. - - - Not enough arguments for Generic. - -