Skip to content
This repository has been archived by the owner on Nov 4, 2024. It is now read-only.

Commit

Permalink
- Fix microsoft#1455: AF: Library module of type Stub has been analyz…
Browse files Browse the repository at this point in the history
…ed already! (microsoft#1470)

- Restore task handling in unit tests
- Throw exception from Debug.Fail instead of FailFast
  • Loading branch information
AlexanderSher authored and MikhailArkhipov committed Aug 22, 2019
1 parent 483d65d commit 1f5c9e0
Show file tree
Hide file tree
Showing 18 changed files with 134 additions and 1,158 deletions.
35 changes: 14 additions & 21 deletions src/Analysis/Ast/Impl/Analyzer/AnalysisModuleKey.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,48 +23,41 @@
namespace Microsoft.Python.Analysis.Analyzer {
[DebuggerDisplay("{Name} : {FilePath}")]
internal readonly struct AnalysisModuleKey : IEquatable<AnalysisModuleKey> {
private enum KeyType { Default, Typeshed, LibraryAsDocument }

private readonly KeyType _type;
public string Name { get; }
public string FilePath { get; }
public bool IsTypeshed => _type == KeyType.Typeshed;
public bool IsLibraryAsDocument => _type == KeyType.LibraryAsDocument;
public bool IsTypeshed { get; }
public bool IsNonUserAsDocument { get; }

public AnalysisModuleKey(IPythonModule module) {
Name = module.Name;
FilePath = module.ModuleType == ModuleType.CompiledBuiltin ? null : module.FilePath;
_type = module is StubPythonModule stub && stub.IsTypeshed
? KeyType.Typeshed
: module.ModuleType == ModuleType.Library && module is IDocument document && document.IsOpen
? KeyType.LibraryAsDocument
: KeyType.Default;
IsTypeshed = module is StubPythonModule stub && stub.IsTypeshed;
IsNonUserAsDocument = (module.IsNonUserFile() || module.IsCompiled()) && module is IDocument document && document.IsOpen;
}

public AnalysisModuleKey(string name, string filePath, bool isTypeshed) {
Name = name;
FilePath = filePath;
_type = isTypeshed ? KeyType.Typeshed : KeyType.Default;
}
public AnalysisModuleKey(string name, string filePath, bool isTypeshed)
: this(name, filePath, isTypeshed, false) { }

private AnalysisModuleKey(string name, string filePath, KeyType type) {
private AnalysisModuleKey(string name, string filePath, bool isTypeshed, bool isNonUserAsDocument) {
Name = name;
FilePath = filePath;
_type = type;
IsTypeshed = isTypeshed;
IsNonUserAsDocument = isNonUserAsDocument;
}

public AnalysisModuleKey GetLibraryAsDocumentKey() => new AnalysisModuleKey(Name, FilePath, KeyType.LibraryAsDocument);
public AnalysisModuleKey GetNonUserAsDocumentKey() => new AnalysisModuleKey(Name, FilePath, IsTypeshed, true);

public bool Equals(AnalysisModuleKey other)
=> Name.EqualsOrdinal(other.Name) && FilePath.PathEquals(other.FilePath) && _type == other._type;
=> Name.EqualsOrdinal(other.Name) && FilePath.PathEquals(other.FilePath) && IsTypeshed == other.IsTypeshed && IsNonUserAsDocument == other.IsNonUserAsDocument;

public override bool Equals(object obj) => obj is AnalysisModuleKey other && Equals(other);

public override int GetHashCode() {
unchecked {
var hashCode = (Name != null ? Name.GetHashCode() : 0);
var hashCode = Name != null ? Name.GetHashCode() : 0;
hashCode = (hashCode * 397) ^ (FilePath != null ? FilePath.GetPathHashCode() : 0);
hashCode = (hashCode * 397) ^ _type.GetHashCode();
hashCode = (hashCode * 397) ^ IsTypeshed.GetHashCode();
hashCode = (hashCode * 397) ^ IsNonUserAsDocument.GetHashCode();
return hashCode;
}
}
Expand Down
14 changes: 10 additions & 4 deletions src/Analysis/Ast/Impl/Analyzer/PythonAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Python.Analysis.Caching;
Expand Down Expand Up @@ -164,9 +165,9 @@ public void EnqueueDocumentForAnalysis(IPythonModule module, PythonAst ast, int
// It is possible that parsing request for the library has been started when document is open,
// but it is closed at the moment of analysis and then become open again.
// In this case, we still need to analyze the document, but using correct entry.
var libraryAsDocumentKey = key.GetLibraryAsDocumentKey();
if (entry.PreviousAnalysis is LibraryAnalysis && _analysisEntries.TryGetValue(libraryAsDocumentKey, out var documentEntry)) {
key = libraryAsDocumentKey;
var nonUserAsDocumentKey = key.GetNonUserAsDocumentKey();
if (entry.PreviousAnalysis is LibraryAnalysis && _analysisEntries.TryGetValue(nonUserAsDocumentKey, out var documentEntry)) {
key = nonUserAsDocumentKey;
entry = documentEntry;
}

Expand Down Expand Up @@ -237,7 +238,7 @@ private void AnalyzeDocument(in AnalysisModuleKey key, in PythonAnalyzerEntry en
ActivityTracker.StartTracking();
_log?.Log(TraceEventType.Verbose, $"Analysis of {entry.Module.Name}({entry.Module.ModuleType}) queued");

var graphVersion = _dependencyResolver.ChangeValue(key, entry, entry.IsUserOrBuiltin || key.IsLibraryAsDocument, dependencies);
var graphVersion = _dependencyResolver.ChangeValue(key, entry, entry.IsUserOrBuiltin || key.IsNonUserAsDocument, dependencies);

lock (_syncObj) {
if (_version > graphVersion) {
Expand Down Expand Up @@ -299,6 +300,11 @@ private bool TryCreateSession(in int graphVersion, in PythonAnalyzerEntry entry,
}

private void StartNextSession(Task task) {
if (task.IsFaulted && task.Exception != null) {
var exception = task.Exception.InnerException;
ExceptionDispatchInfo.Capture(exception).Throw();
}

PythonAnalyzerSession session;
lock (_syncObj) {
if (_nextSession == null) {
Expand Down
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 @@ -113,7 +113,7 @@ public bool IsValidVersion(int version, out IPythonModule module, out PythonAst
}

if (ast == null) {
Debug.Assert(!(_previousAnalysis is LibraryAnalysis), $"Library module {module.Name} of type {module.ModuleType} has been analyzed already!");
Debug.Assert(!(_analysisVersion <= version && _previousAnalysis is LibraryAnalysis), $"Library module {module.Name} of type {module.ModuleType} has been analyzed already!");
return false;
}

Expand Down
8 changes: 7 additions & 1 deletion src/Analysis/Ast/Impl/Analyzer/PythonAnalyzerSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using System.Diagnostics;
using System.Linq;
using System.Runtime;
using System.Runtime.ExceptionServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Python.Analysis.Analyzer.Evaluation;
Expand All @@ -28,6 +29,7 @@
using Microsoft.Python.Core;
using Microsoft.Python.Core.Logging;
using Microsoft.Python.Core.Services;
using Microsoft.Python.Core.Testing;
using Microsoft.Python.Parsing.Ast;

namespace Microsoft.Python.Analysis.Analyzer {
Expand Down Expand Up @@ -207,6 +209,7 @@ private async Task<int> AnalyzeAffectedEntriesAsync(Stopwatch stopWatch) {
if (Interlocked.Increment(ref _runningTasks) >= _maxTaskRunning || _walker.Remaining == 1) {
RunAnalysis(node, stopWatch);
} else {
ace.AddOne();
StartAnalysis(node, ace, stopWatch).DoNotWait();
}
}
Expand Down Expand Up @@ -247,7 +250,6 @@ private Task StartAnalysis(IDependencyChainNode<PythonAnalyzerEntry> node, Async
/// </summary>
private void Analyze(IDependencyChainNode<PythonAnalyzerEntry> node, AsyncCountdownEvent ace, Stopwatch stopWatch) {
try {
ace?.AddOne();
var entry = node.Value;

if (!entry.IsValidVersion(_walker.Version, out var module, out var ast)) {
Expand Down Expand Up @@ -370,6 +372,10 @@ private void LogException(IPythonModule module, Exception exception) {
if (_log != null) {
_log.Log(TraceEventType.Verbose, $"Analysis of {module.Name}({module.ModuleType}) failed. {exception}");
}

if (TestEnvironment.Current != null) {
ExceptionDispatchInfo.Capture(exception).Throw();
}
}

private IDocumentAnalysis CreateAnalysis(IDependencyChainNode<PythonAnalyzerEntry> node, IDocument document, PythonAst ast, int version, ModuleWalker walker, bool isCanceled) {
Expand Down
17 changes: 16 additions & 1 deletion src/Analysis/Ast/Impl/Extensions/FunctionDefinitionExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
using Microsoft.Python.Analysis.Types;
// 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.Types;

namespace Microsoft.Python.Analysis {
public static class ClassMemberExtensions {
Expand Down
3 changes: 3 additions & 0 deletions src/Analysis/Ast/Impl/Extensions/PythonModuleExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,5 +67,8 @@ internal static string GetComment(this IPythonModule module, int lineNum) {

return line.Substring(commentPos + 1).Trim('\t', ' ');
}

internal static bool IsNonUserFile(this IPythonModule module) => module.ModuleType.IsNonUserFile();
internal static bool IsCompiled(this IPythonModule module) => module.ModuleType.IsCompiled();
}
}
10 changes: 0 additions & 10 deletions src/Analysis/Ast/Impl/Extensions/PythonTypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,5 @@ public static bool IsGenericParameter(this IPythonType value)

public static bool IsGeneric(this IPythonType value)
=> value is IGenericTypeParameter || (value is IGenericType gt && gt.IsGeneric);

public static void TransferDocumentationAndLocation(this IPythonType s, IPythonType d) {
if (s != d && s is PythonType src && d is PythonType dst) {
var documentation = src.Documentation;
if (!string.IsNullOrEmpty(documentation)) {
dst.SetDocumentation(documentation);
}
dst.Location = src.Location;
}
}
}
}
5 changes: 5 additions & 0 deletions src/Analysis/Ast/Impl/Modules/Definitions/ModuleType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,9 @@ public enum ModuleType {
/// </summary>
Specialized
}

public static class ModuleTypeExtensions {
public static bool IsNonUserFile(this ModuleType type) => type == ModuleType.Library || type == ModuleType.Stub;
public static bool IsCompiled(this ModuleType type) => type == ModuleType.Compiled || type == ModuleType.CompiledBuiltin;
}
}
8 changes: 7 additions & 1 deletion src/Core/Impl/Extensions/TaskExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
using System.Runtime.ExceptionServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Python.Core.Threading;
using Microsoft.Python.Core.Testing;

namespace Microsoft.Python.Core {
public static class TaskExtensions {
Expand Down Expand Up @@ -52,6 +52,12 @@ private static void SetCompletionResultToContinuation<T>(Task<T> task, object st
/// <see cref="OperationCanceledException"/> is always ignored.
/// </remarks>
public static void DoNotWait(this Task task) {
if (TestEnvironment.Current != null && TestEnvironment.Current.TryAddTaskToWait(task)) {
if (!task.IsCompleted) {
return;
}
}

if (task.IsCompleted) {
ReThrowTaskException(task);
return;
Expand Down
1 change: 0 additions & 1 deletion src/Core/Test/TestLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ public void Dispose() {
public TraceEventType LogLevel { get; set; } = TraceEventType.Verbose;
public void Log(TraceEventType eventType, IFormattable message) => Log(eventType, message.ToString());
public void Log(TraceEventType eventType, string message) {

var m = $"[{TestEnvironmentImpl.Elapsed()}]: {message}";
switch (eventType) {
case TraceEventType.Error:
Expand Down
4 changes: 2 additions & 2 deletions src/PLS.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27929.0
# Visual Studio Version 16
VisualStudioVersion = 16.0.29003.217
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Python.LanguageServer", "LanguageServer\Impl\Microsoft.Python.LanguageServer.csproj", "{4E648207-0C9F-45DB-AA30-84BCDAFE698D}"
EndProject
Expand Down
108 changes: 0 additions & 108 deletions src/UnitTests/Core/Impl/Ben.Demystifier/ILReader.cs

This file was deleted.

Loading

0 comments on commit 1f5c9e0

Please sign in to comment.