Bug 553830: [R-Console] Fix highlighting of current argument in context
information when continuing a function call

Change-Id: I69e82bcf9f1534b04f0780b23c551e5d3763b59d
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 ae283a1..3476ecc 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
@@ -33,7 +33,7 @@
 		IContextInformationExtension {
 	
 	
-	private final int offset;
+	private final int offset; // can be negative for FragmentDocument
 	
 	private final @Nullable ArgsDefinition args;
 	
@@ -52,6 +52,10 @@
 	}
 	
 	
+	public int getCallArgsOffset() {
+		return this.offset;
+	}
+	
 	public @Nullable ArgsDefinition getArguments() {
 		return this.args;
 	}
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 95a5106..da294e4 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
@@ -28,10 +28,11 @@
 import org.eclipse.statet.jcommons.lang.Nullable;
 import org.eclipse.statet.jcommons.text.core.input.OffsetStringParserInput;
 
+import org.eclipse.statet.ecommons.text.core.FragmentDocument;
+
 import org.eclipse.statet.ltk.ast.core.AstInfo;
 import org.eclipse.statet.ltk.ui.sourceediting.assist.AssistCompletionInformationProposalWrapper;
 import org.eclipse.statet.r.core.model.ArgsDefinition;
-import org.eclipse.statet.r.core.rsource.ast.FCall;
 import org.eclipse.statet.r.core.rsource.ast.FCall.Args;
 import org.eclipse.statet.r.core.rsource.ast.RAst;
 import org.eclipse.statet.r.core.rsource.ast.RAst.FCallArgMatch;
@@ -45,9 +46,7 @@
 	private ITextViewer viewer;
 	private int startOffset;
 	
-	private @Nullable IContextInformation info;
-	
-	private @Nullable RArgumentListContextInformation argInfo;
+	private @Nullable RArgumentListContextInformation info;
 	private int currentParameter;
 	private long scannedArgsStamp;
 	private @Nullable Args scannedArgs;
@@ -68,12 +67,11 @@
 		this.scannedArgs= null;
 		this.lastPresentation= -2;
 		if (info instanceof RArgumentListContextInformation) {
-			this.info= this.argInfo= (RArgumentListContextInformation) info;
+			this.info= (RArgumentListContextInformation) info;
 			this.currentParameter= -1;
 		}
 		else {
-			this.info= info;
-			this.argInfo= null;
+			this.info= null;
 			return;
 		}
 		this.viewer= viewer;
@@ -82,45 +80,41 @@
 	
 	@Override
 	public boolean isContextInformationValid(final int offset) {
-		if (this.info == null) {
+		final RArgumentListContextInformation info= this.info;
+		if (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());
-			}
+		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 (this.info == null) {
+		final RArgumentListContextInformation info= this.info;
+		if (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= argInfo.getInformationDisplayStringArgumentIdxs();
-				if (argIndex >= 0 && argIndex < idxs.length) {
-					if (argIndex == this.lastPresentation) {
-						return false;
-					}
-					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));
-					this.lastPresentation= argIndex;
-					return true;
+		final ArgsDefinition args= info.getArguments();
+		if (args != null && args.size() > 0) {
+			final int argIndex= getCurrentArgInFDef(offset);
+			final int[] idxs= info.getInformationDisplayStringArgumentIdxs();
+			if (argIndex >= 0 && argIndex < idxs.length) {
+				if (argIndex == this.lastPresentation) {
+					return false;
 				}
+				final int start= idxs[argIndex];
+				final int stop= (argIndex+1 < idxs.length) ? idxs[argIndex+1] : info.getInformationDisplayString().length();
+				presentation.clear();
+				presentation.addStyleRange(new StyleRange(start, stop-start, null, null, SWT.BOLD));
+				this.lastPresentation= argIndex;
+				return true;
 			}
 		}
 		if (this.lastPresentation >= 0) {
@@ -131,16 +125,26 @@
 		return false;
 	}
 	
-	private FCall. @Nullable Args getScannedArgs() {
-		final AbstractDocument document= (AbstractDocument) this.viewer.getDocument();
+	private @Nullable Args getScannedArgs() {
+		AbstractDocument document= (AbstractDocument)this.viewer.getDocument();
+		final int startOffset= this.info.getCallArgsOffset();
+		int docStartOffset= startOffset;
+		if (document instanceof FragmentDocument) {
+			final FragmentDocument fragmentDoc= (FragmentDocument)document;
+			document= fragmentDoc.getMasterDocument();
+			docStartOffset+= fragmentDoc.getOffsetInMasterDocument();
+		}
+		if (docStartOffset < 0) {
+			docStartOffset= 0;
+		}
 		final long stamp= document.getModificationStamp();
 		if (this.scannedArgs == null || this.scannedArgsStamp != stamp) {
 			try {
-				final String text= document.get(this.startOffset, Math.min(0x800, document.getLength() - this.startOffset));
+				final String text= document.get(docStartOffset, Math.min(0x800, document.getLength() - docStartOffset));
 				final RScanner scanner= new RScanner(AstInfo.LEVEL_MODEL_DEFAULT);
 				this.scannedArgs= scanner.scanFCallArgs(
-						new OffsetStringParserInput(text, this.startOffset)
-								.init(this.startOffset, this.startOffset + text.length()),
+						new OffsetStringParserInput(text, startOffset)
+								.init(startOffset, startOffset + text.length()),
 						true );
 				this.scannedArgsStamp= stamp;
 			}
@@ -158,7 +162,7 @@
 		if (args != null) {
 			final int callArgIdx= getCurrentArgInFCall(args, offset);
 			if (callArgIdx >= 0) {
-				final FCallArgMatch match= RAst.matchArgs(args, this.argInfo.getArguments());
+				final FCallArgMatch match= RAst.matchArgs(args, this.info.getArguments());
 				final ArgsDefinition.Arg argDef= match.getArgDef(callArgIdx);
 				if (argDef != null) {
 					return argDef.index;
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 11d87cc..e2cf87a 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
@@ -177,7 +177,8 @@
 			final ApplyData applyData= getApplyData();
 			
 			applyData.clearSelection();
-			applyData.setContextInformation(new RArgumentListContextInformation(replacementOffset,
+			applyData.setContextInformation(new RArgumentListContextInformation(
+					getReplacementOffset(), // allow negative offsets
 					(IRMethod) getElement() ));
 		}
 		
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 515940b..984cc3b 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
@@ -649,7 +649,7 @@
 		final RAssistInvocationContext.FCallInfo fCallInfo= context.getFCallInfo();
 		if (fCallInfo != null) {
 			final RElementProposalParameters parameters= new RElementProposalParameters(
-					context, Math.max(fCallInfo.getNode().getArgsOpenOffset() + 1, 0),
+					context, fCallInfo.getNode().getArgsOpenOffset() + 1,
 					this.labelProvider );
 			
 			final FCallNamePattern pattern= new FCallNamePattern(fCallInfo.getAccess()) {