[SourceEditor] Fix NPE in InfoHoverRegistry when settings changed

Change-Id: I8d96b9a29a33b82594dba55ee40c8eb482473f89
diff --git a/ltk/org.eclipse.statet.ltk.ui/src/org/eclipse/statet/ltk/ui/sourceediting/assist/InfoHoverRegistry.java b/ltk/org.eclipse.statet.ltk.ui/src/org/eclipse/statet/ltk/ui/sourceediting/assist/InfoHoverRegistry.java
index 2272c87..f6167e6 100644
--- a/ltk/org.eclipse.statet.ltk.ui/src/org/eclipse/statet/ltk/ui/sourceediting/assist/InfoHoverRegistry.java
+++ b/ltk/org.eclipse.statet.ltk.ui/src/org/eclipse/statet/ltk/ui/sourceediting/assist/InfoHoverRegistry.java
@@ -30,6 +30,9 @@
 import org.eclipse.ui.statushandlers.StatusManager;
 
 import org.eclipse.statet.jcommons.lang.Disposable;
+import org.eclipse.statet.jcommons.lang.NonNull;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
 
 import org.eclipse.statet.ecommons.preferences.PreferencesUtil;
 import org.eclipse.statet.ecommons.preferences.SettingsChangeNotifier;
@@ -46,6 +49,7 @@
 /**
  * Registry for information hover types of a content type.
  */
+@NonNullByDefault
 public class InfoHoverRegistry implements ManageListener, Disposable {
 	
 	
@@ -71,7 +75,7 @@
 			return this.stateMasks;
 		}
 		
-		public InfoHoverDescriptor getDescriptor(final int stateMask) {
+		public @Nullable InfoHoverDescriptor getDescriptor(final int stateMask) {
 			for (final InfoHoverDescriptor descriptor : this.stateMaskDescriptors) {
 				if (descriptor.getStateMask() == stateMask) {
 					return descriptor;
@@ -92,8 +96,8 @@
 	private final String settingsGroupId;
 	private final StringArrayPref prefTypeSettings;
 	
-	private List<InfoHoverDescriptor> descriptors;
-	private EffectiveHovers effectiveHovers;
+	private @Nullable List<InfoHoverDescriptor> descriptors;
+	private @Nullable EffectiveHovers effectiveHovers;
 	
 	
 	public InfoHoverRegistry(final String contentTypeId, final String prefQualifier,
@@ -119,8 +123,12 @@
 	public void beforeSettingsChangeNotification(final Set<String> groupIds) {
 		if (this.settingsGroupId != null && groupIds.contains(this.settingsGroupId)) {
 			synchronized (this) {
-				this.descriptors= applyPreferences(PreferenceUtils.getInstancePrefs(),
-						new ArrayList<>(this.descriptors));
+				List<InfoHoverDescriptor> descriptors= this.descriptors;
+				if (descriptors != null) {
+					descriptors= applyPreferences(PreferenceUtils.getInstancePrefs(),
+							new ArrayList<>(descriptors) );
+					this.descriptors= descriptors;
+				}
 				this.effectiveHovers= null;
 			}
 		}
@@ -204,7 +212,7 @@
 	
 	Map<Preference<?>, Object> toPreferencesMap(final List<InfoHoverDescriptor> descriptors) {
 		final Map<Preference<?>, Object> map= new HashMap<>();
-		final String[] settings= new String[descriptors.size()];
+		final String[] settings= new @NonNull String[descriptors.size()];
 		for (int i= 0; i < settings.length; i++) {
 			final InfoHoverDescriptor descriptor= descriptors.get(i);
 			settings[i]= descriptor.getId() + ':' + descriptor.isEnabled() + ';' + 
@@ -219,7 +227,7 @@
 		return this.contentTypeId;
 	}
 	
-	public synchronized InfoHoverDescriptor getHoverDescriptor(final int stateMask) {
+	public synchronized @Nullable InfoHoverDescriptor getHoverDescriptor(final int stateMask) {
 		List<InfoHoverDescriptor> descriptors= this.descriptors;
 		if (descriptors == null) {
 			this.descriptors= descriptors= loadCurrent();
@@ -233,13 +241,15 @@
 	}
 	
 	public synchronized EffectiveHovers getEffectiveHoverDescriptors() {
-		if (this.effectiveHovers == null) {
-			updateEffectiveHovers();
+		EffectiveHovers effectiveHovers= this.effectiveHovers;
+		if (effectiveHovers == null) {
+			effectiveHovers= gatherEffectiveHovers();
+			this.effectiveHovers= effectiveHovers;
 		}
-		return this.effectiveHovers;
+		return effectiveHovers;
 	}
 	
-	private void updateEffectiveHovers() {
+	private EffectiveHovers gatherEffectiveHovers() {
 		List<InfoHoverDescriptor> descriptors= this.descriptors;
 		if (descriptors == null) {
 			this.descriptors= descriptors= loadCurrent();
@@ -270,7 +280,7 @@
 			System.arraycopy(stateMasks, 0, fittedMasks, 0, effectiveDescriptors.size());
 			stateMasks= fittedMasks;
 		}
-		this.effectiveHovers= new EffectiveHovers(stateMasks, effectiveDescriptors, combinedDescriptors);
+		return new EffectiveHovers(stateMasks, effectiveDescriptors, combinedDescriptors);
 	}
 	
 }