Skip to content
Browse files

Added more visible error handling

  • Loading branch information...
1 parent fc7c900 commit 2fae6d08e5d661bc9018261cfc52e3e571837e35 @citizenmatt citizenmatt committed Jan 18, 2013
View
89 src/resharper-nuget/Hacks.cs
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2012 JetBrains s.r.o.
+ *
+ * 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
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using JetBrains.ActionManagement;
+using JetBrains.Application;
+using JetBrains.Application.Progress;
+using JetBrains.DataFlow;
+using JetBrains.ProjectModel;
+using JetBrains.ReSharper.Psi;
+using JetBrains.TextControl;
+using JetBrains.Threading;
+using JetBrains.UI.Application;
+using JetBrains.Util;
+
+namespace JetBrains.ReSharper.Plugins.NuGet
+{
+ internal static class Hacks
+ {
+ public static void PokeReSharpersAssemblyReferences(IPsiModule module,
+ IEnumerable<FileSystemPath> assemblyLocations,
+ string packageLocation,
+ IProjectPsiModule projectModule)
+ {
+ if (string.IsNullOrEmpty(packageLocation))
+ return;
+
+ // TODO: I wish we didn't have to do this
+ // When NuGet references the assemblies, they are queued up to be processed, but after
+ // this method completes. Which means the import type part of the process fails to find
+ // the type to import. We force an update which works through the system early. It would
+ // be nice to find out if we can process the proper import notifications instead
+ using (var cookie = module.GetSolution()
+ .CreateTransactionCookie(DefaultAction.Commit, "ReferenceModuleWithType",
+ NullProgressIndicator.Instance))
+ {
+ var assemblyLocation = assemblyLocations.FirstOrDefault(
+ l => l.FullPath.StartsWith(packageLocation, StringComparison.InvariantCultureIgnoreCase));
+ if (!assemblyLocation.IsNullOrEmpty())
+ cookie.AddAssemblyReference(projectModule.Project, assemblyLocation);
+ }
+ }
+
+ public static void HandleFailureToReference(string packageLocation, ITextControlManager textControlManager, IShellLocks shellLocks)
+ {
+ // TODO: Wish we didn't have to do this, either
+ // If we failed to install the package, it's because something has gone wrong,
+ // and we don't want the rest of the process to continue. Unfortunately, ReSharper
+ // doesn't display any error messages, so we'll very hackily try and find the
+ // current text editor, and display a tooltip with an error message.
+ // (This replicates the experience when something else goes wrong in the context
+ // actions that use ModuleReferencerService.) It's not a nice thing to do, but
+ // it's safe with how ReSharper uses IModuleReferencer out of the box. If anyone
+ // else uses it, and we go wrong, well, fingers crossed. We should either get
+ // the tooltip as expected, multiple error messages, or no error messages. Hopefully,
+ // we shouldn't see this very often, although I've probably just jinxed it now...
+ //
+ // Ideally, ReSharper should provide a better error mechanism as part of IModuleReferencer
+ if (string.IsNullOrEmpty(packageLocation))
+ {
+ var textControl = textControlManager.FocusedTextControl.Value;
+ if (textControl != null)
+ {
+ var shell = Shell.Instance;
+ shellLocks.Queue("Failed to import type",
+ () => shell.Components.Tooltips().ShowAtCaret(EternalLifetime.Instance,
+ "Failed to add NuGet package.",
+ textControl, shellLocks,
+ shell.GetComponent<IActionManager>()));
+ }
+ }
+ }
+ }
+}
View
35 src/resharper-nuget/NuGetApi.cs
@@ -53,7 +53,7 @@ public class NuGetApi
}
catch (Exception e)
{
- // NuGet isn't installed
+ Logger.LogException("Unable to get NuGet interfaces. Is NuGet installed?", e);
}
}
@@ -71,28 +71,41 @@ public bool AreAnyAssemblyFilesNuGetPackages(IList<FileSystemPath> fileLocations
var hasPackageAssembly = false;
threading.Dispatcher.Invoke("NuGet", () =>
{
- hasPackageAssembly = GetPackageFromAssemblyLocations(fileLocations) != null;
+ hasPackageAssembly = Logger.Catch(() => GetPackageFromAssemblyLocations(fileLocations) != null);
});
return hasPackageAssembly;
}
- public string InstallNuGetPackageFromAssemblyFiles(IList<FileSystemPath> assemblyLocations, IProject project)
+ // Yeah, that's an out parameter. Bite me.
+ public bool InstallNuGetPackageFromAssemblyFiles(IList<FileSystemPath> assemblyLocations, IProject project, out string installedLocation)
{
- if (!IsNuGetAvailable || assemblyLocations.Count == 0)
- return null;
+ installedLocation = null;
- string installedAssembly = null;
+ if (!IsNuGetAvailable || assemblyLocations.Count == 0)
+ return false;
// We're talking to NuGet via COM. Make sure we're on the UI thread
- threading.Dispatcher.Invoke("NuGet", () =>
+ string location = null;
+ threading.Dispatcher.Invoke("NuGet", () => Logger.Catch(() =>
{
+// ReSharper disable RedundantAssignment - it's not redundant, evaluation happens immediately
var vsProject = GetVsProject(project);
if (vsProject != null)
- installedAssembly = DoInstallAssemblyAsNuGetPackage(assemblyLocations, vsProject);
- });
-
- return installedAssembly;
+ location = DoInstallAssemblyAsNuGetPackage(assemblyLocations, vsProject);
+// ReSharper restore RedundantAssignment
+ }));
+ installedLocation = location;
+
+ // Even if there's been an exception, return true to say that it's installed.
+ // What's happened is that we know we should import a nuget package, but it's
+ // failed. It's worse to then let the default fallback behaviour kick in (i.e.
+ // import a file reference to a nuget installed dll).
+ // It would be better if the ModuleReferencerService would find the first
+ // IModuleReferencer that can add the reference, and only allow that one to
+ // have a go - no fallback. If we can handle it, but it fails, then no-one
+ // else should get a go
+ return true;
}
private string DoInstallAssemblyAsNuGetPackage(IEnumerable<FileSystemPath> assemblyLocations, Project vsProject)
View
41 src/resharper-nuget/NuGetModuleReferencer.cs
@@ -14,14 +14,13 @@
* limitations under the License.
*/
-using System;
using System.Collections.Generic;
+using JetBrains.Application;
using JetBrains.Application.Components;
-using JetBrains.Application.Progress;
-using JetBrains.ProjectModel;
using JetBrains.ProjectModel.Model2.Assemblies.Interfaces;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.Module;
+using JetBrains.TextControl;
using JetBrains.Util;
using System.Linq;
@@ -38,10 +37,14 @@ public class NuGetModuleReferencer : IModuleReferencer
private const int NuGetModuleReferencerPriority = 100;
private readonly NuGetApi nuget;
+ private readonly ITextControlManager textControlManager;
+ private readonly IShellLocks shellLocks;
- public NuGetModuleReferencer(NuGetApi nuget)
+ public NuGetModuleReferencer(NuGetApi nuget, ITextControlManager textControlManager, IShellLocks shellLocks)
{
this.nuget = nuget;
+ this.textControlManager = textControlManager;
+ this.shellLocks = shellLocks;
}
public bool CanReferenceModule(IPsiModule module, IPsiModule moduleToReference)
@@ -61,11 +64,16 @@ public bool ReferenceModule(IPsiModule module, IPsiModule moduleToReference)
var assemblyLocations = GetAllAssemblyLocations(moduleToReference);
var projectModule = (IProjectPsiModule)module;
- var packageLocation = nuget.InstallNuGetPackageFromAssemblyFiles(assemblyLocations, projectModule.Project);
- PokeReSharpersAssemblyReferences(module, assemblyLocations, packageLocation, projectModule);
+ string packageLocation;
+ var handled = nuget.InstallNuGetPackageFromAssemblyFiles(assemblyLocations, projectModule.Project, out packageLocation);
+ if (handled)
+ {
+ Hacks.PokeReSharpersAssemblyReferences(module, assemblyLocations, packageLocation, projectModule);
+ Hacks.HandleFailureToReference(packageLocation, textControlManager, shellLocks);
+ }
- return !string.IsNullOrEmpty(packageLocation);
+ return handled;
}
public bool ReferenceModuleWithType(IPsiModule module, ITypeElement typeToReference)
@@ -101,24 +109,5 @@ private static IList<FileSystemPath> GetAllAssemblyLocations(IPsiModule psiModul
return (from f in projectModelAssembly.GetFiles()
select f.Location).ToList();
}
-
- private static void PokeReSharpersAssemblyReferences(IPsiModule module, IEnumerable<FileSystemPath> assemblyLocations, string packageLocation,
- IProjectPsiModule projectModule)
- {
- if (string.IsNullOrEmpty(packageLocation))
- return;
-
- // TODO: I wish we didn't have to do this
- // When NuGet references the assemblies, they are queued up to be processed, but after
- // this method completes. Which means the import type part of the process fails to find
- // the type to import. We force an update which works through the system early. It would
- // be nice to find out if we can process the proper import notifications instead
- using (var cookie = module.GetSolution().CreateTransactionCookie(DefaultAction.Commit, "ReferenceModuleWithType", NullProgressIndicator.Instance))
- {
- var assemblyLocation = assemblyLocations.FirstOrDefault(l => l.FullPath.StartsWith(packageLocation, StringComparison.InvariantCultureIgnoreCase));
- if (!assemblyLocation.IsNullOrEmpty())
- cookie.AddAssemblyReference(projectModule.Project, assemblyLocation);
- }
- }
}
}
View
1 src/resharper-nuget/resharper-nuget.6.1.csproj
@@ -61,6 +61,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="ExposeNuGetServices.cs" />
+ <Compile Include="Hacks.cs" />
<Compile Include="NuGetApi.cs" />
<Compile Include="NuGetModuleReferencer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
View
1 src/resharper-nuget/resharper-nuget.7.1.csproj
@@ -61,6 +61,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="ExposeNuGetServices.cs" />
+ <Compile Include="Hacks.cs" />
<Compile Include="NuGetApi.cs" />
<Compile Include="NuGetModuleReferencer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

0 comments on commit 2fae6d0

Please sign in to comment.
Something went wrong with that request. Please try again.