Explorar o código

Merge pull request #995 from kekekeks/null-checks

Set PlatformImpl to null on close + null checks enforced by static analyzer
Nikita Tsukanov %!s(int64=8) %!d(string=hai) anos
pai
achega
5d8546f529

+ 1 - 0
Avalonia.sln.DotSettings

@@ -1,4 +1,5 @@
 <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
+	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=3E53A01A_002DB331_002D47F3_002DB828_002D4A5717E77A24_002Fd_003Aglass/@EntryIndexedValue">ExplicitlyExcluded</s:String>
 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=6417B24E_002D49C2_002D4985_002D8DB2_002D3AB9D898EC91/@EntryIndexedValue">ExplicitlyExcluded</s:String>
 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=E3A1060B_002D50D0_002D44E8_002D88B6_002DF44EF2E5BD72_002Ff_003Ahtml_002Ehtm/@EntryIndexedValue">ExplicitlyExcluded</s:String>
 	<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantUsingDirective/@EntryIndexedValue">HINT</s:String>

+ 1 - 0
appveyor.yml

@@ -35,6 +35,7 @@ test: off
 artifacts:
   - path: artifacts\nuget\*.nupkg
   - path: artifacts\zip\*.zip
+  - path: artifacts\inspectcode.xml
 cache:
   - gtk-sharp-2.12.26.msi
   - dotnet-1.0.1.exe

+ 37 - 2
build.cake

@@ -5,7 +5,8 @@
 #addin "nuget:?package=Polly&version=4.2.0"
 #addin "nuget:?package=NuGet.Core&version=2.12.0"
 #tool "nuget:https://dotnet.myget.org/F/nuget-build/?package=NuGet.CommandLine&version=4.3.0-preview1-3980&prerelease"
-#tool "nuget:?package=JetBrains.dotMemoryUnit&version=2.1.20150828.125449"
+#tool "nuget:?package=JetBrains.dotMemoryUnit&version=2.3.20160517.113140"
+#tool "JetBrains.ReSharper.CommandLineTools"
 ///////////////////////////////////////////////////////////////////////////////
 // TOOLS
 ///////////////////////////////////////////////////////////////////////////////
@@ -104,7 +105,7 @@ Task("Restore-NuGet-Packages")
     .Does(() =>
 {
     var maxRetryCount = 5;
-    var toolTimeout = 1d;
+    var toolTimeout = 2d;
     Policy
         .Handle<Exception>()
         .Retry(maxRetryCount, (exception, retryCount, context) => {
@@ -287,6 +288,7 @@ Task("Zip-Files")
 
 Task("Create-NuGet-Packages")
     .IsDependentOn("Run-Unit-Tests")
+    .IsDependentOn("Inspect")
     .Does(() =>
 {
     foreach(var nuspec in packages.NuspecNuGetSettings)
@@ -363,6 +365,39 @@ Task("Publish-NuGet")
     Information("Publish-NuGet Task failed, but continuing with next Task...");
 });
 
+Task("Inspect")
+    .WithCriteria(parameters.IsRunningOnWindows)
+    .IsDependentOn("Restore-NuGet-Packages")
+    .Does(() =>
+    {
+        var badIssues = new []{"PossibleNullReferenceException"};
+        var whitelist = new []{"tests", "src\\android", "src\\ios",
+            "src\\windows\\avalonia.designer", "src\\avalonia.htmlrenderer\\external"};
+        Information("Running code inspections");
+        
+        
+        StartProcess("tools\\JetBrains.ReSharper.CommandLineTools\\tools\\inspectcode.exe",
+            new ProcessSettings{ Arguments = "--output=artifacts\\inspectcode.xml --profile=Avalonia.sln.DotSettings Avalonia.sln" });
+        Information("Analyzing report");
+        var doc = XDocument.Parse(System.IO.File.ReadAllText("artifacts\\inspectcode.xml"));
+        var failBuild = false;
+        foreach(var xml in doc.Descendants("Issue"))
+        {
+            var typeId = xml.Attribute("TypeId").Value.ToString();
+            if(badIssues.Contains(typeId))
+            {
+                var file = xml.Attribute("File").Value.ToString().ToLower();
+                if(whitelist.Any(wh => file.StartsWith(wh)))
+                    continue;
+                var line = xml.Attribute("Line").Value.ToString();
+                Error(typeId + " - " + file + " on line " + line);
+                failBuild = true;
+            }
+        }
+        if(failBuild)
+            throw new Exception("Issues found");
+    });
+
 ///////////////////////////////////////////////////////////////////////////////
 // TARGETS
 ///////////////////////////////////////////////////////////////////////////////

+ 1 - 1
samples/interop/Direct3DInteropSample/MainWindow.cs

@@ -58,7 +58,7 @@ namespace Direct3DInteropSample
                    new ModeDescription((int)ClientSize.Width, (int)ClientSize.Height,
                             new Rational(60, 1), Format.R8G8B8A8_UNorm),
                 IsWindowed = true,
-                OutputHandle = PlatformImpl.Handle.Handle,
+                OutputHandle = PlatformImpl?.Handle.Handle ?? IntPtr.Zero,
                 SampleDescription = new SampleDescription(1, 0),
                 SwapEffect = SwapEffect.Discard,
                 Usage = Usage.RenderTargetOutput

+ 3 - 8
src/Avalonia.Base/AvaloniaObject.cs

@@ -622,14 +622,9 @@ namespace Avalonia
         /// <returns>The default value.</returns>
         private object GetDefaultValue(AvaloniaProperty property)
         {
-            if (property.Inherits && _inheritanceParent != null)
-            {
-                return (_inheritanceParent as AvaloniaObject).GetValueInternal(property);
-            }
-            else
-            {
-                return ((IStyledPropertyAccessor)property).GetDefaultValue(GetType());
-            }
+            if (property.Inherits && _inheritanceParent is AvaloniaObject aobj)
+                return aobj.GetValueInternal(property);
+            return ((IStyledPropertyAccessor) property).GetDefaultValue(GetType());
         }
 
         /// <summary>

+ 9 - 16
src/Avalonia.Base/Collections/AvaloniaDictionary.cs

@@ -103,11 +103,9 @@ namespace Avalonia.Collections
 
             _inner = new Dictionary<TKey, TValue>();
 
-            if (PropertyChanged != null)
-            {
-                PropertyChanged(this, new PropertyChangedEventArgs("Count"));
-                PropertyChanged(this, new PropertyChangedEventArgs($"Item[]"));
-            }
+            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Count"));
+            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs($"Item[]"));
+            
 
             if (CollectionChanged != null)
             {
@@ -144,12 +142,9 @@ namespace Avalonia.Collections
 
             if (_inner.TryGetValue(key, out value))
             {
-                if (PropertyChanged != null)
-                {
-                    PropertyChanged(this, new PropertyChangedEventArgs("Count"));
-                    PropertyChanged(this, new PropertyChangedEventArgs($"Item[{key}]"));
-                }
-
+                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Count"));
+                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs($"Item[{key}]"));
+                
                 if (CollectionChanged != null)
                 {
                     var e = new NotifyCollectionChangedEventArgs(
@@ -199,11 +194,9 @@ namespace Avalonia.Collections
 
         private void NotifyAdd(TKey key, TValue value)
         {
-            if (PropertyChanged != null)
-            {
-                PropertyChanged(this, new PropertyChangedEventArgs("Count"));
-                PropertyChanged(this, new PropertyChangedEventArgs($"Item[{key}]"));
-            }
+            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Count"));
+            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs($"Item[{key}]"));
+            
 
             if (CollectionChanged != null)
             {

+ 1 - 1
src/Avalonia.Base/PriorityValue.cs

@@ -285,7 +285,7 @@ namespace Avalonia
                     Property.Name, 
                     _valueType, 
                     value,
-                    value.GetType());
+                    value?.GetType());
             }
         }
     }

+ 1 - 1
src/Avalonia.Controls/Button.cs

@@ -275,7 +275,7 @@ namespace Avalonia.Controls
         {
             var button = e.Sender as Button;
             var isDefault = (bool)e.NewValue;
-            var inputRoot = button.VisualRoot as IInputElement;
+            var inputRoot = button?.VisualRoot as IInputElement;
 
             if (inputRoot != null)
             {

+ 1 - 1
src/Avalonia.Controls/Control.cs

@@ -645,7 +645,7 @@ namespace Avalonia.Controls
 
             if (_focusAdorner != null)
             {
-                var adornerLayer = _focusAdorner.Parent as Panel;
+                var adornerLayer = (IPanel)_focusAdorner.Parent;
                 adornerLayer.Children.Remove(_focusAdorner);
                 _focusAdorner = null;
             }

+ 6 - 6
src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs

@@ -4,6 +4,7 @@ using Avalonia.Input;
 using Avalonia.Layout;
 using Avalonia.Platform;
 using Avalonia.Styling;
+using JetBrains.Annotations;
 
 namespace Avalonia.Controls.Embedding
 {
@@ -18,6 +19,7 @@ namespace Avalonia.Controls.Embedding
         {
         }
 
+        [CanBeNull]
         public new IEmbeddableWindowImpl PlatformImpl => (IEmbeddableWindowImpl) base.PlatformImpl;
 
         public void Prepare()
@@ -39,8 +41,9 @@ namespace Avalonia.Controls.Embedding
 
         protected override Size MeasureOverride(Size availableSize)
         {
-            base.MeasureOverride(PlatformImpl.ClientSize);
-            return PlatformImpl.ClientSize;
+            var cs = PlatformImpl?.ClientSize ?? default(Size);
+            base.MeasureOverride(cs);
+            return cs;
         }
 
         private readonly NameScope _nameScope = new NameScope();
@@ -63,9 +66,6 @@ namespace Avalonia.Controls.Embedding
         public void Unregister(string name) => _nameScope.Unregister(name);
 
         Type IStyleable.StyleKey => typeof(EmbeddableControlRoot);
-        public void Dispose()
-        {
-            PlatformImpl.Dispose();
-        }
+        public void Dispose() => PlatformImpl?.Dispose();
     }
 }

+ 1 - 1
src/Avalonia.Controls/ItemsControl.cs

@@ -354,7 +354,7 @@ namespace Avalonia.Controls
             }
 
             var collection = sender as ICollection;
-            PseudoClasses.Set(":empty", collection.Count == 0);
+            PseudoClasses.Set(":empty", collection == null || collection.Count == 0);
         }
 
         /// <summary>

+ 3 - 4
src/Avalonia.Controls/Primitives/PopupRoot.cs

@@ -9,6 +9,7 @@ using Avalonia.Layout;
 using Avalonia.Media;
 using Avalonia.Platform;
 using Avalonia.VisualTree;
+using JetBrains.Annotations;
 
 namespace Avalonia.Controls.Primitives
 {
@@ -49,6 +50,7 @@ namespace Avalonia.Controls.Primitives
         /// <summary>
         /// Gets the platform-specific window implementation.
         /// </summary>
+        [CanBeNull]
         public new IPopupImpl PlatformImpl => (IPopupImpl)base.PlatformImpl;
 
         /// <summary>
@@ -65,10 +67,7 @@ namespace Avalonia.Controls.Primitives
         IVisual IHostedVisualTreeRoot.Host => Parent;
 
         /// <inheritdoc/>
-        public void Dispose()
-        {
-            this.PlatformImpl.Dispose();
-        }
+        public void Dispose() => PlatformImpl?.Dispose();
 
         /// <inheritdoc/>
         protected override void OnTemplateApplied(TemplateAppliedEventArgs e)

+ 5 - 2
src/Avalonia.Controls/TextBox.cs

@@ -720,7 +720,7 @@ namespace Avalonia.Controls
                         if (pos < text.Length)
                         {
                             --pos;
-                            if (pos > 0 && Text[pos - 1] == '\r' && Text[pos] == '\n')
+                            if (pos > 0 && text[pos - 1] == '\r' && text[pos] == '\n')
                             {
                                 --pos;
                             }
@@ -771,6 +771,9 @@ namespace Avalonia.Controls
 
         private string GetSelection()
         {
+            var text = Text;
+            if (string.IsNullOrEmpty(text))
+                return "";
             var selectionStart = SelectionStart;
             var selectionEnd = SelectionEnd;
             var start = Math.Min(selectionStart, selectionEnd);
@@ -779,7 +782,7 @@ namespace Avalonia.Controls
             {
                 return "";
             }
-            return Text.Substring(start, end - start);
+            return text.Substring(start, end - start);
         }
 
         private int GetLine(int caretIndex, IList<FormattedTextLine> lines)

+ 19 - 16
src/Avalonia.Controls/TopLevel.cs

@@ -14,6 +14,7 @@ using Avalonia.Platform;
 using Avalonia.Rendering;
 using Avalonia.Styling;
 using Avalonia.VisualTree;
+using JetBrains.Annotations;
 
 namespace Avalonia.Controls
 {
@@ -92,25 +93,25 @@ namespace Avalonia.Controls
             var rendererFactory = TryGetService<IRendererFactory>(dependencyResolver);
             Renderer = rendererFactory?.CreateRenderer(this, renderLoop);
 
-            PlatformImpl.SetInputRoot(this);
+            impl.SetInputRoot(this);
 
-            PlatformImpl.Closed = HandleClosed;
-            PlatformImpl.Input = HandleInput;
-            PlatformImpl.Paint = HandlePaint;
-            PlatformImpl.Resized = HandleResized;
-            PlatformImpl.ScalingChanged = HandleScalingChanged;
+            impl.Closed = HandleClosed;
+            impl.Input = HandleInput;
+            impl.Paint = HandlePaint;
+            impl.Resized = HandleResized;
+            impl.ScalingChanged = HandleScalingChanged;
 
 
             _keyboardNavigationHandler?.SetOwner(this);
             _accessKeyHandler?.SetOwner(this);
             styler?.ApplyStyles(this);
 
-            ClientSize = PlatformImpl.ClientSize;
+            ClientSize = impl.ClientSize;
             
             this.GetObservable(PointerOverElementProperty)
                 .Select(
                     x => (x as InputElement)?.GetObservable(CursorProperty) ?? Observable.Empty<Cursor>())
-                .Switch().Subscribe(cursor => PlatformImpl.SetCursor(cursor?.PlatformCursor));
+                .Switch().Subscribe(cursor => PlatformImpl?.SetCursor(cursor?.PlatformCursor));
 
             if (_applicationLifecycle != null)
             {
@@ -135,10 +136,8 @@ namespace Avalonia.Controls
         /// <summary>
         /// Gets the platform-specific window implementation.
         /// </summary>
-        public ITopLevelImpl PlatformImpl
-        {
-            get;
-        }
+        [CanBeNull]
+        public ITopLevelImpl PlatformImpl { get; private set; }
         
         /// <summary>
         /// Gets the renderer for the window.
@@ -177,7 +176,7 @@ namespace Avalonia.Controls
         Size ILayoutRoot.MaxClientSize => Size.Infinity;
 
         /// <inheritdoc/>
-        double ILayoutRoot.LayoutScaling => PlatformImpl.Scaling;
+        double ILayoutRoot.LayoutScaling => PlatformImpl?.Scaling ?? 1;
 
         IStyleHost IStyleHost.StylingParent
         {
@@ -189,25 +188,27 @@ namespace Avalonia.Controls
         /// <inheritdoc/>
         protected virtual IRenderTarget CreateRenderTarget()
         {
+            if(PlatformImpl == null)
+                throw new InvalidOperationException("Cann't create render target, PlatformImpl is null (might be already disposed)");
             return _renderInterface.CreateRenderTarget(PlatformImpl.Surfaces);
         }
 
         /// <inheritdoc/>
         void IRenderRoot.Invalidate(Rect rect)
         {
-            PlatformImpl.Invalidate(rect);
+            PlatformImpl?.Invalidate(rect);
         }
 
         /// <inheritdoc/>
         Point IRenderRoot.PointToClient(Point p)
         {
-            return PlatformImpl.PointToClient(p);
+            return PlatformImpl?.PointToClient(p) ?? default(Point);
         }
 
         /// <inheritdoc/>
         Point IRenderRoot.PointToScreen(Point p)
         {
-            return PlatformImpl.PointToScreen(p);
+            return PlatformImpl?.PointToScreen(p) ?? default(Point);
         }
 
         /// <summary>
@@ -224,6 +225,8 @@ namespace Avalonia.Controls
         /// </summary>
         protected virtual void HandleClosed()
         {
+            PlatformImpl = null;
+
             Closed?.Invoke(this, EventArgs.Empty);
             Renderer?.Dispose();
             Renderer = null;

+ 17 - 11
src/Avalonia.Controls/Window.cs

@@ -12,6 +12,7 @@ using Avalonia.Platform;
 using Avalonia.Styling;
 using System.Collections.Generic;
 using System.Linq;
+using JetBrains.Annotations;
 
 namespace Avalonia.Controls
 {
@@ -87,11 +88,11 @@ namespace Avalonia.Controls
         static Window()
         {
             BackgroundProperty.OverrideDefaultValue(typeof(Window), Brushes.White);
-            TitleProperty.Changed.AddClassHandler<Window>((s, e) => s.PlatformImpl.SetTitle((string)e.NewValue));
+            TitleProperty.Changed.AddClassHandler<Window>((s, e) => s.PlatformImpl?.SetTitle((string)e.NewValue));
             HasSystemDecorationsProperty.Changed.AddClassHandler<Window>(
-                (s, e) => s.PlatformImpl.SetSystemDecorations((bool) e.NewValue));
+                (s, e) => s.PlatformImpl?.SetSystemDecorations((bool) e.NewValue));
 
-            IconProperty.Changed.AddClassHandler<Window>((s, e) => s.PlatformImpl.SetIcon(((WindowIcon)e.NewValue).PlatformImpl));
+            IconProperty.Changed.AddClassHandler<Window>((s, e) => s.PlatformImpl?.SetIcon(((WindowIcon)e.NewValue).PlatformImpl));
         }
 
         /// <summary>
@@ -109,7 +110,7 @@ namespace Avalonia.Controls
         public Window(IWindowImpl impl)
             : base(impl)
         {
-            _maxPlatformClientSize = this.PlatformImpl.MaxClientSize;
+            _maxPlatformClientSize = PlatformImpl?.MaxClientSize ?? default(Size);
         }
 
         /// <inheritdoc/>
@@ -129,6 +130,7 @@ namespace Avalonia.Controls
         /// <summary>
         /// Gets the platform-specific window implementation.
         /// </summary>
+        [CanBeNull]
         public new IWindowImpl PlatformImpl => (IWindowImpl)base.PlatformImpl;
 
         /// <summary>
@@ -164,8 +166,12 @@ namespace Avalonia.Controls
         /// </summary>
         public WindowState WindowState
         {
-            get { return this.PlatformImpl.WindowState; }
-            set { this.PlatformImpl.WindowState = value; }
+            get { return PlatformImpl?.WindowState ?? WindowState.Normal; }
+            set
+            {
+                if (PlatformImpl != null)
+                    PlatformImpl.WindowState = value;
+            }
         }
 
         /// <summary>
@@ -189,7 +195,7 @@ namespace Avalonia.Controls
         public void Close()
         {
             s_windows.Remove(this);
-            PlatformImpl.Dispose();
+            PlatformImpl?.Dispose();
             IsVisible = false;
         }
 
@@ -221,7 +227,7 @@ namespace Avalonia.Controls
         {
             using (BeginAutoSizing())
             {
-                PlatformImpl.Hide();
+                PlatformImpl?.Hide();
             }
 
             IsVisible = false;
@@ -240,7 +246,7 @@ namespace Avalonia.Controls
 
             using (BeginAutoSizing())
             {
-                PlatformImpl.Show();
+                PlatformImpl?.Show();
             }
         }
 
@@ -278,7 +284,7 @@ namespace Avalonia.Controls
                 var activated = affectedWindows.Where(w => w.IsActive).FirstOrDefault();
                 SetIsEnabled(affectedWindows, false);
 
-                var modal = PlatformImpl.ShowDialog();
+                var modal = PlatformImpl?.ShowDialog();
                 var result = new TaskCompletionSource<TResult>();
 
                 Observable.FromEventPattern<EventHandler, EventArgs>(
@@ -287,7 +293,7 @@ namespace Avalonia.Controls
                     .Take(1)
                     .Subscribe(_ =>
                     {
-                        modal.Dispose();
+                        modal?.Dispose();
                         SetIsEnabled(affectedWindows, true);
                         activated?.Activate();
                         result.SetResult((TResult)_dialogResult);

+ 20 - 14
src/Avalonia.Controls/WindowBase.cs

@@ -9,6 +9,7 @@ using Avalonia.Controls.Primitives;
 using Avalonia.Input;
 using Avalonia.Layout;
 using Avalonia.Platform;
+using JetBrains.Annotations;
 
 namespace Avalonia.Controls
 {
@@ -43,10 +44,10 @@ namespace Avalonia.Controls
 
         public WindowBase(IWindowBaseImpl impl, IAvaloniaDependencyResolver dependencyResolver) : base(impl, dependencyResolver)
         {
-            PlatformImpl.Activated = HandleActivated;
-            PlatformImpl.Deactivated = HandleDeactivated;
-            PlatformImpl.PositionChanged = HandlePositionChanged;
-            this.GetObservable(ClientSizeProperty).Skip(1).Subscribe(x => PlatformImpl.Resize(x));
+            impl.Activated = HandleActivated;
+            impl.Deactivated = HandleDeactivated;
+            impl.PositionChanged = HandlePositionChanged;
+            this.GetObservable(ClientSizeProperty).Skip(1).Subscribe(x => PlatformImpl?.Resize(x));
         }
 
         /// <summary>
@@ -64,6 +65,7 @@ namespace Avalonia.Controls
         /// </summary>
         public event EventHandler<PointEventArgs> PositionChanged;
 
+        [CanBeNull]
         public new IWindowBaseImpl PlatformImpl => (IWindowBaseImpl) base.PlatformImpl;
 
         /// <summary>
@@ -80,8 +82,12 @@ namespace Avalonia.Controls
         /// </summary>
         public Point Position
         {
-            get { return PlatformImpl.Position; }
-            set { PlatformImpl.Position = value; }
+            get { return PlatformImpl?.Position ?? default(Point); }
+            set
+            {
+                if (PlatformImpl is IWindowBaseImpl impl)
+                    impl.Position = value;
+            }
         }
 
         /// <summary>
@@ -98,7 +104,7 @@ namespace Avalonia.Controls
         /// </summary>
         public void Activate()
         {
-            PlatformImpl.Activate();
+            PlatformImpl?.Activate();
         }
 
         /// <summary>
@@ -110,7 +116,7 @@ namespace Avalonia.Controls
 
             try
             {
-                PlatformImpl.Hide();
+                PlatformImpl?.Hide();
                 IsVisible = false;
             }
             finally
@@ -131,7 +137,7 @@ namespace Avalonia.Controls
                 EnsureInitialized();
                 IsVisible = true;
                 LayoutManager.Instance.ExecuteInitialLayoutPass(this);
-                PlatformImpl.Show();
+                PlatformImpl?.Show();
             }
             finally
             {
@@ -163,10 +169,10 @@ namespace Avalonia.Controls
         {
             using (BeginAutoSizing())
             {
-                PlatformImpl.Resize(finalSize);
+                PlatformImpl?.Resize(finalSize);
             }
 
-            return base.ArrangeOverride(PlatformImpl.ClientSize);
+            return base.ArrangeOverride(PlatformImpl?.ClientSize ?? default(Size));
         }
 
         /// <summary>
@@ -174,7 +180,7 @@ namespace Avalonia.Controls
         /// </summary>
         protected void EnsureInitialized()
         {
-            if (!this.IsInitialized)
+            if (!IsInitialized)
             {
                 var init = (ISupportInitialize)this;
                 init.BeginInit();
@@ -268,12 +274,12 @@ namespace Avalonia.Controls
         /// <summary>
         /// Starts moving a window with left button being held. Should be called from left mouse button press event handler
         /// </summary>
-        public void BeginMoveDrag() => PlatformImpl.BeginMoveDrag();
+        public void BeginMoveDrag() => PlatformImpl?.BeginMoveDrag();
 
         /// <summary>
         /// Starts resizing a window. This function is used if an application has window resizing controls. 
         /// Should be called from left mouse button press event handler
         /// </summary>
-        public void BeginResizeDrag(WindowEdge edge) => PlatformImpl.BeginResizeDrag(edge);
+        public void BeginResizeDrag(WindowEdge edge) => PlatformImpl?.BeginResizeDrag(edge);
     }
 }

+ 3 - 1
src/Avalonia.DesignerSupport/DesignerAssist.cs

@@ -75,7 +75,7 @@ namespace Avalonia.DesignerSupport
         private static void SetScalingFactor(double factor)
         {
             PlatformManager.SetDesignerScalingFactor(factor);
-            s_currentWindow?.PlatformImpl.Resize(s_currentWindow.ClientSize);
+            s_currentWindow?.PlatformImpl?.Resize(s_currentWindow.ClientSize);
         }
 
         static Window s_currentWindow;
@@ -149,6 +149,8 @@ namespace Avalonia.DesignerSupport
             s_currentWindow = window;
             window.Show();
             Design.ApplyDesignerProperties(window, control);
+            // ReSharper disable once PossibleNullReferenceException
+            // Always not null at this point
             Api.OnWindowCreated?.Invoke(window.PlatformImpl.Handle.Handle);
             Api.OnResize?.Invoke();
         }

+ 7 - 1
src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs

@@ -82,7 +82,13 @@ namespace Avalonia
 
         private void LoadAssembliesInDirectory()
         {
-            foreach (var file in new FileInfo(Assembly.GetEntryAssembly().Location).Directory.EnumerateFiles("*.dll"))
+            var location = Assembly.GetEntryAssembly().Location;
+            if (string.IsNullOrWhiteSpace(location))
+                return;
+            var dir = new FileInfo(location).Directory;
+            if (dir == null)
+                return;
+            foreach (var file in dir.EnumerateFiles("*.dll"))
             {
                 try
                 {

+ 1 - 1
src/Avalonia.Styling/Controls/NameScope.cs

@@ -50,7 +50,7 @@ namespace Avalonia.Controls
                     return result;
                 }
 
-                visual = (visual as ILogical).LogicalParent as Visual;
+                visual = (visual as ILogical)?.LogicalParent as Visual;
             }
 
             return null;

+ 1 - 1
src/Avalonia.Visuals/Rendering/ZIndexComparer.cs

@@ -8,6 +8,6 @@ namespace Avalonia.Rendering
     {
         public static readonly ZIndexComparer Instance = new ZIndexComparer();
 
-        public int Compare(IVisual x, IVisual y) => x.ZIndex.CompareTo(y.ZIndex);
+        public int Compare(IVisual x, IVisual y) => (x?.ZIndex ?? 0).CompareTo(y?.ZIndex ?? 0);
     }
 }

+ 1 - 0
src/Gtk/Avalonia.Cairo/Media/DrawingContext.cs

@@ -9,6 +9,7 @@ using Avalonia.Cairo.Media.Imaging;
 using Avalonia.Media;
 using Avalonia.Platform;
 using Avalonia.Rendering;
+// ReSharper disable PossibleNullReferenceException
 
 namespace Avalonia.Cairo.Media
 {

+ 1 - 0
src/Gtk/Avalonia.Gtk3/SystemDialogs.cs

@@ -28,6 +28,7 @@ namespace Avalonia.Gtk3
             List<IDisposable> disposables = null;
             Action dispose = () =>
             {
+                // ReSharper disable once PossibleNullReferenceException
                 foreach (var d in disposables)
                     d.Dispose();
                 disposables.Clear();

+ 1 - 1
src/Markup/Avalonia.Markup.Xaml/Parsers/SelectorParser.cs

@@ -68,7 +68,7 @@ namespace Avalonia.Markup.Xaml.Parsers
                 }
                 else if (property != null)
                 {
-                    var type = result.TargetType;
+                    var type = result?.TargetType;
 
                     if (type == null)
                     {

+ 3 - 1
src/Windows/Avalonia.Win32/Embedding/WinFormsAvaloniaControlHost.cs

@@ -15,7 +15,7 @@ namespace Avalonia.Win32.Embedding
     {
         private readonly EmbeddableControlRoot _root = new EmbeddableControlRoot();
 
-        private IntPtr WindowHandle => ((WindowImpl) _root.PlatformImpl).Handle.Handle;
+        private IntPtr WindowHandle => ((WindowImpl) _root?.PlatformImpl)?.Handle?.Handle ?? IntPtr.Zero;
 
         public WinFormsAvaloniaControlHost()
         {
@@ -25,6 +25,8 @@ namespace Avalonia.Win32.Embedding
             if (_root.IsFocused)
                 FocusManager.Instance.Focus(null);
             _root.GotFocus += RootGotFocus;
+            // ReSharper disable once PossibleNullReferenceException
+            // Always non-null at this point
             _root.PlatformImpl.LostFocus += PlatformImpl_LostFocus;
             FixPosition();
         }