laurentkempe / GitDiffMargin

Git Diff Margin displays live Git changes of the currently edited file on Visual Studio margin and scroll bar. Supports Visual Studio 2012 through Visual Studio 2022
https://marketplace.visualstudio.com/items?itemName=LaurentKempe.GitDiffMargin
MIT License
290 stars 39 forks source link

Visual Studio 2019 RTM crashes on method parameter add/remove #213

Open xperiandri opened 5 years ago

xperiandri commented 5 years ago

Versions

What happened

I had such controller in my ASP.NET Core 2.2 app

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Auth.Data.Identity;
using Auth.Models;

// For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace Auth.Controllers
{
    public class AccountController : Controller
    {
        private readonly SignInManager<User> signInManager;
        private readonly ILogger<AccountController> logger;

        public AccountController(SignInManager<User> signInManager, ILogger<AccountController> logger)
        {
            this.signInManager = signInManager;
            this.logger = logger;
        }

        [HttpGet]
        [AllowAnonymous]
        public async Task<IActionResult> Login(string returnUrl = null)
        {
            returnUrl = returnUrl ?? Url.Content("~/");
            // Clear the existing external cookie to ensure a clean login process
            await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
            var externalLogin = (await signInManager.GetExternalAuthenticationSchemesAsync()).First();
            return RedirectToAction(nameof(ExternalLogin), new { provider = externalLogin.Name, returnUrl });
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> LogOut(string returnUrl = null)
        {
            await signInManager.SignOutAsync();
            logger.LogInformation("User logged out.");
            if (returnUrl != null)
            {
                return LocalRedirect(returnUrl);
            }
            else
            {
                return RedirectToAction(nameof(HomeController.Index), "Home");
            }
        }

        [HttpGet]
        [AllowAnonymous]
        public IActionResult ExternalLogin(string provider, string returnUrl = null)
        {
            // Request a redirect to the external login provider.
            var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl });
            var properties = signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
            return new ChallengeResult(provider, properties);
        }

        [HttpGet]
        [AllowAnonymous]
        public async Task<IActionResult> ExternalLoginCallback([FromServices] UserManager<User> userManager, string returnUrl = null, string remoteError = null)
        {
            returnUrl = returnUrl ?? Url.Content("~/");
            if (remoteError != null)
                return View("Error", new ErrorViewModel
                {
                    RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier,
                    ErrorDescription = $"Error from external provider: {remoteError}"
                });

            var info = await signInManager.GetExternalLoginInfoAsync();
            if (info == null)
                return View("Error", new ErrorViewModel
                {
                    RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier,
                    ErrorDescription = "Error loading external login information."
                });

            // Sign in the user with this external login provider if the user already has a login.
            string loginProvider = info.LoginProvider;
            var signInResult = await signInManager.ExternalLoginSignInAsync(loginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true);
            var identity = info.Principal.Identity;
            if (signInResult.Succeeded)
            {
                var user = await userManager.FindByLoginAsync(loginProvider, info.ProviderKey);

                // TODO: Update user from identity using Automapper

                var props = new AuthenticationProperties
                {
                    IsPersistent = true
                };
                props.StoreTokens(info.AuthenticationTokens);

                await signInManager.SignInAsync(user, props, loginProvider);

                logger.LogInformation("{Name} logged in with {LoginProvider} provider.", identity.Name, loginProvider);
                return LocalRedirect(returnUrl);
            }
            else
            {
                // If the user does not have an account, create an account.
                var user = new User
                {
                    // TODO: Use Automapper
                    SalesforceInstance = identity.GetInstanceUrl(),
                    UserName = identity.GetUserName(),
                    Email = identity.GetEmail(),
                    FirstName = identity.GetFirstName(),
                    LastName = identity.GetLastName(),
                    SalesforceId = identity.GetSalesforceId(),
                    SalesforceOrg = identity.GetSalesforceOrg(),
                    Picture = identity.GetPicture(),
                    Thumbnail = identity.GetThumbnail()
                };
                var createResult = await userManager.CreateAsync(user);
                if (createResult.Succeeded)
                {
                    createResult = await userManager.AddLoginAsync(user, info);
                    if (createResult.Succeeded)
                    {
                        var props = new AuthenticationProperties();
                        props.StoreTokens(info.AuthenticationTokens);

                        await signInManager.SignInAsync(user, props, loginProvider);
                        logger.LogInformation("User created an account using {Name} provider.", loginProvider);
                        return LocalRedirect(returnUrl);
                    }
                }
                foreach (var error in createResult.Errors)
                {
                    ModelState.AddModelError(string.Empty, error.Description);
                }
            }

            return BadRequest(ModelState);
        }
    }
}

I also had C# Var Type CodeLens extension installed.

So I selected , string remoteError = null in ExternalLoginCallback method and deleted it. Usually Visual Studio crashed without any info (see my discussion in Q&A) However 1 time in event log I found crash with GitDiffMargin. Then I disabled GitDiffMargin and tried to investigate further to find the next cause of crash.

Application: devenv.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.ArgumentException
   at Microsoft.VisualStudio.Text.SnapshotSpan.EnsureSnapshot(Microsoft.VisualStudio.Text.ITextSnapshot)
   at Microsoft.VisualStudio.Text.SnapshotSpan.IntersectsWith(Microsoft.VisualStudio.Text.SnapshotSpan)
   at GitDiffMargin.EditorDiffMargin.UpdateNormalDiffDimensions(GitDiffMargin.ViewModel.DiffViewModel, GitDiffMargin.Git.HunkRangeInfo)
   at GitDiffMargin.EditorDiffMargin.UpdateDiffDimensions(GitDiffMargin.ViewModel.DiffViewModel, GitDiffMargin.Git.HunkRangeInfo)
   at GitDiffMargin.ViewModel.DiffViewModel.UpdateDimensions()
   at GitDiffMargin.ViewModel.EditorDiffViewModel.UpdateDimensions()
   at GitDiffMargin.ViewModel.EditorDiffViewModel..ctor(GitDiffMargin.Git.HunkRangeInfo, GitDiffMargin.Core.IMarginCore, System.Action`2<GitDiffMargin.ViewModel.DiffViewModel,GitDiffMargin.Git.HunkRangeInfo>)
   at GitDiffMargin.ViewModel.EditorDiffMarginViewModel.CreateDiffViewModel(GitDiffMargin.Git.HunkRangeInfo)
   at System.Linq.Enumerable+WhereSelectListIterator`2[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].MoveNext()
   at GitDiffMargin.ViewModel.DiffMarginViewModelBase.HandleHunksChanged(System.Object, GitDiffMargin.Core.HunksChangedEventArgs)
   at GitDiffMargin.ViewModel.EditorDiffMarginViewModel.HandleHunksChanged(System.Object, GitDiffMargin.Core.HunksChangedEventArgs)
   at System.EventHandler`1[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].Invoke(System.Object, System.__Canon)
   at GitDiffMargin.Core.MarginCore.OnHunksChanged(System.Collections.Generic.IEnumerable`1<GitDiffMargin.Git.HunkRangeInfo>)
   at GitDiffMargin.Core.MarginCore+<>c__DisplayClass58_0.<HandleParseComplete>b__0()
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(System.Object)
   at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(System.Object)
   at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
   at MS.Internal.CulturePreservingExecutionContext.Run(MS.Internal.CulturePreservingExecutionContext, System.Threading.ContextCallback, System.Object)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.ProcessQueue()
   at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)
   at MS.Win32.HwndWrapper.WndProc(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(System.Object)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority, System.TimeSpan, System.Delegate, System.Object, Int32)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr)

Steps to Reproduce

Steps to reproduce the behavior:

  1. Create ASP.NET Core 2.2 app
  2. Add controller with code from above
  3. Selected , string remoteError = null in ExternalLoginCallback method and deleted it.
  4. Visual Studio might crash

Additional context

Crash may occure with C# Var Type CodeLens extension

laurentkempe commented 5 years ago

Thx for reporting the bug @xperiandri Could you extend the Steps to Reproduce with how you do to "on method parameter add/remove"

xperiandri commented 5 years ago

Updated description