Bug 538952: [R-Editor] Fix context information

Change-Id: I24baf3af1aa654f466e4f811b16b45e49a386b6c
diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/editors/RArgumentListContextInformation.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/editors/RArgumentListContextInformation.java
index 8b266ea..ae283a1 100644
--- a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/editors/RArgumentListContextInformation.java
+++ b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/editors/RArgumentListContextInformation.java
@@ -19,6 +19,8 @@
 
 import org.eclipse.statet.jcommons.collections.IntArrayList;
 import org.eclipse.statet.jcommons.collections.IntList;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
 
 import org.eclipse.statet.ltk.ui.sourceediting.assist.AssistInformationProposal;
 import org.eclipse.statet.r.core.model.ArgsDefinition;
@@ -26,13 +28,14 @@
 import org.eclipse.statet.r.ui.RLabelProvider;
 
 
+@NonNullByDefault
 public class RArgumentListContextInformation implements AssistInformationProposal,
 		IContextInformationExtension {
 	
 	
 	private final int offset;
 	
-	private final ArgsDefinition args;
+	private final @Nullable ArgsDefinition args;
 	
 	private final String information;
 	private final int[] informationIndexes;
@@ -49,12 +52,12 @@
 	}
 	
 	
-	public ArgsDefinition getArguments() {
+	public @Nullable ArgsDefinition getArguments() {
 		return this.args;
 	}
 	
 	@Override
-	public Image getImage() {
+	public @Nullable Image getImage() {
 		return null;
 	}
 	
@@ -78,7 +81,7 @@
 	}
 	
 	@Override
-	public boolean equals(final Object obj) {
+	public boolean equals(final @Nullable Object obj) {
 		// prevent stacking of context information at the same position
 		return true;
 	}
diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/editors/RContextInformationValidator.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/editors/RContextInformationValidator.java
index bf010bd..95a5106 100644
--- a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/editors/RContextInformationValidator.java
+++ b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/editors/RContextInformationValidator.java
@@ -24,6 +24,8 @@
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.StyleRange;
 
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
 import org.eclipse.statet.jcommons.text.core.input.OffsetStringParserInput;
 
 import org.eclipse.statet.ltk.ast.core.AstInfo;
@@ -36,21 +38,21 @@
 import org.eclipse.statet.r.core.rsource.ast.RScanner;
 
 
+@NonNullByDefault
 public class RContextInformationValidator implements IContextInformationValidator, IContextInformationPresenter {
 	
 	
-	private ITextViewer fViewer;
-	private int fStartOffset;
+	private ITextViewer viewer;
+	private int startOffset;
 	
-	private IContextInformation fInfo;
+	private @Nullable IContextInformation info;
 	
-	private RArgumentListContextInformation fArgInfo;
-	private int fCurrentParameter;
-//	private RScanner scanner;
-	private long fScannedArgsStamp;
-	private Args fScannedArgs;
+	private @Nullable RArgumentListContextInformation argInfo;
+	private int currentParameter;
+	private long scannedArgsStamp;
+	private @Nullable Args scannedArgs;
 	
-	private int fLastPresentation = -2;
+	private int lastPresentation= -2;
 	
 	
 	public RContextInformationValidator() {
@@ -58,122 +60,125 @@
 	
 	
 	@Override
-	public boolean isContextInformationValid(final int offset) {
-		if (fInfo == null) {
-			return false;
-		}
-		final IDocument document = fViewer.getDocument();
-		if (offset < fStartOffset || offset > document.getLength()) {
-			return false;
-		}
-		if (fArgInfo != null) {
-			final Args args = getScannedArgs();
-			if (args != null) {
-				return (offset <= args.getEndOffset());
-			}
-		}
-		return (offset == fStartOffset);
-	}
-	
-	@Override
 	public void install(IContextInformation info, final ITextViewer viewer, final int offset) {
 		if (info instanceof AssistCompletionInformationProposalWrapper) {
 			info= ((AssistCompletionInformationProposalWrapper) info).getContextInformation();
 		}
 		
-		fScannedArgs = null;
-		fLastPresentation = -2;
+		this.scannedArgs= null;
+		this.lastPresentation= -2;
 		if (info instanceof RArgumentListContextInformation) {
-			fInfo = fArgInfo = (RArgumentListContextInformation) info;
-			fCurrentParameter = -1;
+			this.info= this.argInfo= (RArgumentListContextInformation) info;
+			this.currentParameter= -1;
 		}
 		else {
-			fInfo = info;
-			fArgInfo = null;
+			this.info= info;
+			this.argInfo= null;
 			return;
 		}
-		fViewer = viewer;
-		fStartOffset = offset;
+		this.viewer= viewer;
+		this.startOffset= offset;
+	}
+	
+	@Override
+	public boolean isContextInformationValid(final int offset) {
+		if (this.info == null) {
+			return false;
+		}
+		final IDocument document= this.viewer.getDocument();
+		if (offset < this.startOffset || offset > document.getLength()) {
+			return false;
+		}
+		final RArgumentListContextInformation argInfo= this.argInfo;
+		if (argInfo != null) {
+			final Args args= getScannedArgs();
+			if (args != null) {
+				return (offset <= args.getEndOffset());
+			}
+		}
+		return (offset == this.startOffset);
 	}
 	
 	@Override
 	public boolean updatePresentation(final int offset, final TextPresentation presentation) {
-		if (fArgInfo != null) {
-			final ArgsDefinition args = fArgInfo.getArguments();
+		if (this.info == null) {
+			return false;
+		}
+		final RArgumentListContextInformation argInfo= this.argInfo;
+		if (argInfo != null) {
+			final ArgsDefinition args= argInfo.getArguments();
 			if (args != null && args.size() > 0) {
-				final int argIndex = getCurrentArgInFDef(offset);
-				final int[] idxs = fArgInfo.getInformationDisplayStringArgumentIdxs();
+				final int argIndex= getCurrentArgInFDef(offset);
+				final int[] idxs= argInfo.getInformationDisplayStringArgumentIdxs();
 				if (argIndex >= 0 && argIndex < idxs.length) {
-					if (argIndex == fLastPresentation) {
+					if (argIndex == this.lastPresentation) {
 						return false;
 					}
-					final int start = idxs[argIndex];
-					final int stop = (argIndex+1 < idxs.length) ? idxs[argIndex+1] : fArgInfo.getInformationDisplayString().length();
+					final int start= idxs[argIndex];
+					final int stop= (argIndex+1 < idxs.length) ? idxs[argIndex+1] : argInfo.getInformationDisplayString().length();
 					presentation.clear();
 					presentation.addStyleRange(new StyleRange(start, stop-start, null, null, SWT.BOLD));
-					fLastPresentation = argIndex;
+					this.lastPresentation= argIndex;
 					return true;
 				}
 			}
 		}
-		if (fLastPresentation == -1) {
-			return false;
+		if (this.lastPresentation >= 0) {
+			presentation.clear();
+			this.lastPresentation= -1;
+			return true;
 		}
-		presentation.clear();
-		presentation.addStyleRange(new StyleRange(0, fInfo.getInformationDisplayString().length(),
-				null, null, SWT.NORMAL));
-		fLastPresentation = -1;
-		return true;
+		return false;
 	}
 	
-	private FCall.Args getScannedArgs() {
-		final AbstractDocument document = (AbstractDocument) fViewer.getDocument();
-		final long stamp = document.getModificationStamp();
-		if (fScannedArgs == null || fScannedArgsStamp != stamp) {
+	private FCall. @Nullable Args getScannedArgs() {
+		final AbstractDocument document= (AbstractDocument) this.viewer.getDocument();
+		final long stamp= document.getModificationStamp();
+		if (this.scannedArgs == null || this.scannedArgsStamp != stamp) {
 			try {
-				final String text= document.get(fStartOffset, Math.min(0x800, document.getLength() - fStartOffset));
+				final String text= document.get(this.startOffset, Math.min(0x800, document.getLength() - this.startOffset));
 				final RScanner scanner= new RScanner(AstInfo.LEVEL_MODEL_DEFAULT);
-				fScannedArgs= scanner.scanFCallArgs(
-						new OffsetStringParserInput(text, fStartOffset)
-								.init(fStartOffset, fStartOffset + text.length()),
+				this.scannedArgs= scanner.scanFCallArgs(
+						new OffsetStringParserInput(text, this.startOffset)
+								.init(this.startOffset, this.startOffset + text.length()),
 						true );
-				fScannedArgsStamp = stamp;
+				this.scannedArgsStamp= stamp;
 			}
 			catch (final Exception e) {
-				fScannedArgs = null;
+				this.scannedArgs= null;
 			}
 		}
 		
-		return fScannedArgs;
+		return this.scannedArgs;
 	}
 	
+	
 	private int getCurrentArgInFDef(final int offset) {
-		final int callArgIdx= getCurrentArgInFCall(offset);
-		if (callArgIdx >= 0) {
-			final FCallArgMatch match= RAst.matchArgs(getScannedArgs(), fArgInfo.getArguments());
-			final ArgsDefinition.Arg argDef= match.getArgDef(callArgIdx);
-			if (argDef != null) {
-				return argDef.index;
+		final Args args= getScannedArgs();
+		if (args != null) {
+			final int callArgIdx= getCurrentArgInFCall(args, offset);
+			if (callArgIdx >= 0) {
+				final FCallArgMatch match= RAst.matchArgs(args, this.argInfo.getArguments());
+				final ArgsDefinition.Arg argDef= match.getArgDef(callArgIdx);
+				if (argDef != null) {
+					return argDef.index;
+				}
 			}
 		}
 		return -1;
 	}
 	
-	private int getCurrentArgInFCall(final int offset) {
-		final Args args = getScannedArgs();
-		if (args != null) {
-			final int last = args.getChildCount()-1;
-			if (last == -1) {
-				return 0;
-			}
-			for (int i = 0; i < last; i++) {
-				if (offset <= args.getSeparatorOffset(i)) {
-					return i;
-				}
-			}
-			return last;
+	private static int getCurrentArgInFCall(final Args args, final int offset) {
+		final int last= args.getChildCount() - 1;
+		if (last == -1) {
+			return 0;
 		}
-		return -1;
+		for (int i= 0; i < last; i++) {
+			if (offset <= args.getSeparatorOffset(i)) {
+				return i;
+			}
+		}
+		return last;
 	}
 	
 }
diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/editors/RElementCompletionProposal.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/editors/RElementCompletionProposal.java
index 49feacb..137aa55 100644
--- a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/editors/RElementCompletionProposal.java
+++ b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/editors/RElementCompletionProposal.java
@@ -18,7 +18,6 @@
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jface.text.BadLocationException;
-import org.eclipse.jface.text.DocumentEvent;
 import org.eclipse.jface.text.IDocument;
 import org.eclipse.jface.text.IInformationControlCreator;
 import org.eclipse.jface.text.IRegion;
@@ -89,7 +88,17 @@
 		public RElementProposalParameters(final RAssistInvocationContext context, final int replacementOffset,
 				final SearchPattern namePattern,
 				final ElementLabelProvider labelProvider) {
-			this(context, replacementOffset, namePattern, 0, labelProvider);
+			super(context, replacementOffset, namePattern);
+			
+			this.labelProvider= labelProvider;
+		}
+		
+		/** Only for context information */
+		public RElementProposalParameters(final RAssistInvocationContext context, final int replacementOffset,
+				final ElementLabelProvider labelProvider) {
+			super(context, replacementOffset, 0);
+			
+			this.labelProvider= labelProvider;
 		}
 		
 	}
@@ -157,11 +166,6 @@
 		
 		
 		@Override
-		public boolean validate(final IDocument document, final int offset, final DocumentEvent event) {
-			return (offset == getInvocationContext().getInvocationOffset());
-		}
-		
-		@Override
 		public boolean isAutoInsertable() {
 			return true;
 		}
diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/sourceediting/RElementCompletionComputer.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/sourceediting/RElementCompletionComputer.java
index 467a84f..31a0402 100644
--- a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/sourceediting/RElementCompletionComputer.java
+++ b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/sourceediting/RElementCompletionComputer.java
@@ -650,7 +650,6 @@
 		if (fCallInfo != null) {
 			final RElementProposalParameters parameters= new RElementProposalParameters(
 					context, Math.max(fCallInfo.getNode().getArgsOpenOffset() + 1, 0),
-					null,
 					this.labelProvider );
 			
 			final FCallNamePattern pattern= new FCallNamePattern(fCallInfo.getAccess()) {