/*******************************************************************************
* Copyright 2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* The Chisel Group, University of Victoria
* IBM Corporation
*******************************************************************************/
package com.ibm.research.tagging.java.autocomplete;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.ui.text.java.ContentAssistInvocationContext;
import org.eclipse.jdt.ui.text.java.IJavaCompletionProposalComputer;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.swt.graphics.Image;
import com.ibm.research.tagging.core.ITag;
import com.ibm.research.tagging.core.TagCorePlugin;
import com.ibm.research.tagging.core.ui.TagUIPlugin;
/**
* @author mdesmond
*
*/
public class WaypointCompletionProposalComputer implements IJavaCompletionProposalComputer
{
/* get the auto complete image */
private static Image fAutoCompleteImage = null;
public WaypointCompletionProposalComputer() {
}
private Image getAutoCompleteImage()
{
if (fAutoCompleteImage == null)
{
fAutoCompleteImage = TagUIPlugin.getDefault().getImageRegistry().get(TagUIPlugin.IMG_WAYPOINT);
}
return fAutoCompleteImage;
}
/**
* Gets the username from the system properties. Defaults to "unknown".
* @return String the username
*/
@SuppressWarnings("restriction")
private String getSystemUsername() {
return System.getProperty("user.name", "unknown");
}
/* (non-Javadoc)
* @see org.eclipse.jdt.ui.text.java.IJavaCompletionProposalComputer#computeCompletionProposals(org.eclipse.jdt.ui.text.java.ContentAssistInvocationContext, org.eclipse.core.runtime.IProgressMonitor)
*/
public List computeCompletionProposals(ContentAssistInvocationContext context, IProgressMonitor monitor)
{
try
{
int invocationOffset = context.getInvocationOffset();
IDocument document = context.getDocument();
// The line region
final IRegion region= document.getLineInformationOfOffset(invocationOffset);
// The line content
final String content= document.get(region.getOffset(), region.getLength());
int index = invocationOffset - region.getOffset() - 1;
// read back through the line until we hit the @ or the start of the line
// we need the context of the invocation
char c = 0;
while(true)
{
c = content.charAt(index);
if(index == 0 || c=='@')
break;
else
index--;
}
// Compute the tag, keep the @
String workingTag = content.substring(index , invocationOffset - region.getOffset());
// the offset where the tag starts
int tagInsertionOffset = region.getOffset() + index;
/* if its empty or doesnt start with @ then ignore */
if (workingTag.length() > 0 && workingTag.startsWith("@"))
{
// handle the case where the user wants to auto complete the keyword
// becase the keyword is short we can use simple combined if statment
if(workingTag.equals("@") ||
workingTag.equals("@t") ||
workingTag.equals("@ta"))
{
ITag tags[] = TagCorePlugin.getDefault().getTagCore().getTagModel().getTags();
ArrayList<WaypointCompletionProposal> proposals = new ArrayList<WaypointCompletionProposal>();
proposals.add(createEmptyTagCompletionProposal(tagInsertionOffset, workingTag.length()));
// add all available tags
for (ITag t : tags)
proposals.add(createTagCompletionProposal(t.getName(), tagInsertionOffset, workingTag.length()));
return proposals;
}
// we are now working with an existing tag definition somewhere after the tag keyword
if(workingTag.trim().startsWith("@tag"))
{
// we will be scanning backward towards the (@)tag keyword to figure out what
// the context of the invocation is
// this will get complicated
// working char
char ch = 0;
//start offset
int start = "@tag".length();
//end offset
int end = workingTag.length();
// index ranges from 0 to length -1
int i = end - 1;
while(true)
{
if(i <= start)
break;
//populate the working char
ch = workingTag.charAt(i);
//we are intrested in certain cases
/* the last special character is a colon */
if(ch==':')
break;
/* the last special character is an open sq bracket */
else if(ch == '[')
break;
/* the last special character is a semi colon */
else if(ch == ';')
break;
/* the last special character is an equals */
else if(ch == '=')
break;
i--;
}
int proposalLength = ((end - 1) - i);
int proposalOffset = invocationOffset - proposalLength;
// the proposal is the string following the special character to the invocation offset
String proposalString = document.get(proposalOffset,proposalLength);
// the last special char was an open sq bracket
if(ch == '[')
{
ArrayList<WaypointCompletionProposal> proposals = new ArrayList<WaypointCompletionProposal>();
if(proposalString.trim().length() == 0)
{
proposals.add(createUnBracketedMetaDataCompletionProposal(invocationOffset, 0));
proposals.add(createAuthorMetaDataCompletionProposal(invocationOffset, 0));
proposals.add(createDateMetaDataCompletionProposal(invocationOffset, 0));
}
// @tag todo : more cases to handle here
return proposals;
}
// the last special char was a regular colon, we are after the comment section
else if(ch == ':')
{
ArrayList<WaypointCompletionProposal> proposals = new ArrayList<WaypointCompletionProposal>();
// no comment exists
if(proposalString.trim().length() == 0)
proposals.add(createCommentedBracketedMetaDataCompletionProposal(invocationOffset, 0));
// create meta data after the comment
proposals.add(createBracketedMetaDataCompletionProposal(invocationOffset, 0));
return proposals;
}
// the last special char was a regular colon, we are after the comment section
else if(ch == ';')
{
ArrayList<WaypointCompletionProposal> proposals = new ArrayList<WaypointCompletionProposal>();
if(proposalString.trim().length() == 0)
{
proposals.add(createAuthorMetaDataCompletionProposal(invocationOffset, 0));
proposals.add(createDateMetaDataCompletionProposal(invocationOffset, 0));
}
return proposals;
}
else // need a check here
{
// Giggidy! here we go again, reset variables
// working char
ch = 0;
//start offset
start = "@tag".length();
//end offset
end = workingTag.length();
// index ranges from 0 to length -1
i = end - 1;
while(true)
{
if(i <= start)
break;
//populate the working char
ch = workingTag.charAt(i);
//this time we are only intrested in whitespace and open bracket, all other cases
//have been handles
/* the last special character is an open bracket */
if(Character.isWhitespace(ch))
break;
else if(ch =='(')
break;
i--;
}
proposalLength = ((end - 1) - i);
proposalOffset = invocationOffset - proposalLength;
proposalString = document.get(proposalOffset,proposalLength);
ArrayList<WaypointCompletionProposal> proposals = new ArrayList<WaypointCompletionProposal>();
ITag tags[] = TagCorePlugin.getDefault().getTagCore().getTagModel().getTags();
for (ITag t : tags)
{
if (t.getName().startsWith(proposalString))
{
proposals.add(createTagNameCompletionProposal(t.getName(), proposalOffset, proposalLength));
}
}
return proposals;
}
}
}
}
catch (BadLocationException exception)
{
// log & ignore
return Collections.EMPTY_LIST;
}
return Collections.EMPTY_LIST;
}
/**
* Empty Tag name completion proposal with meta data
* @param replacmentOffset
* @param replacmentLength
* @return
*/
private WaypointCompletionProposal createEmptyTagCompletionProposal(int replacmentOffset, int replacmentLength)
{
SimpleDateFormat format = new SimpleDateFormat();
String date = format.format(new Date());
String replacmentString = "@tag : [Author = "+ getSystemUsername()+ ";" + "Date = "+ date +";]";
int caretOffset = "@tag ".length();
WaypointCompletionProposal proposal = new WaypointCompletionProposal(replacmentString,
replacmentOffset,
replacmentLength,
caretOffset,
getAutoCompleteImage(),
"@tag",
(IContextInformation)null,
"Create a new java tag");
return proposal;
}
/**
* Tag name completion proposal with meta data
* @param replacmentOffset
* @param replacmentLength
* @return
*/
private WaypointCompletionProposal createTagCompletionProposal(String tagName, int replacmentOffset, int replacmentLength)
{
SimpleDateFormat format = new SimpleDateFormat();
String date = format.format(new Date());
String tagStart = "@tag " + tagName + " : ";
String tagEnd = " [Author = "+ getSystemUsername()+ ";" + "Date = "+ date +";]";
String replacmentString = tagStart + tagEnd;
int caretOffset = tagStart.length();
WaypointCompletionProposal proposal = new WaypointCompletionProposal(replacmentString,
replacmentOffset,
replacmentLength,
caretOffset,
getAutoCompleteImage(),
"@tag " + tagName,
(IContextInformation)null,
"Create a new java tag");
return proposal;
}
/**
* Simple commented meta data proposal
* @param replacmentOffset
* @param replacmentLength
* @return
*/
private WaypointCompletionProposal createCommentedBracketedMetaDataCompletionProposal(int replacmentOffset, int replacmentLength)
{
SimpleDateFormat format = new SimpleDateFormat();
String date = format.format(new Date());
String replacmentString = "description [Author = "+ getSystemUsername()+ ";" + "Date = "+ date +";]";
int caretOffset = "description".length();
WaypointCompletionProposal proposal = new WaypointCompletionProposal(replacmentString,
replacmentOffset,
replacmentLength,
caretOffset,
getAutoCompleteImage(),
"@tag meta data (default description, Author and date)",
(IContextInformation)null,
"Generate and insert tag meta data (default description, Author and date)");
return proposal;
}
/**
* Simple un commented meta data completion proposal
* @param replacmentOffset
* @param replacmentLength
* @return
*/
private WaypointCompletionProposal createBracketedMetaDataCompletionProposal(int replacmentOffset, int replacmentLength)
{
SimpleDateFormat format = new SimpleDateFormat();
String date = format.format(new Date());
String replacmentString = "[Author = "+ getSystemUsername()+ ";" + "Date = "+ date +";]";
int caretOffset = 0;
WaypointCompletionProposal proposal = new WaypointCompletionProposal(replacmentString,
replacmentOffset,
replacmentLength,
caretOffset,
getAutoCompleteImage(),
"@tag meta data (Author and date)",
(IContextInformation)null,
"Generate and insert tag meta data (Author and date)");
return proposal;
}
/**
* Simple un commented meta data completion proposal
* @param replacmentOffset
* @param replacmentLength
* @return
*/
private WaypointCompletionProposal createUnBracketedMetaDataCompletionProposal(int replacmentOffset, int replacmentLength)
{
SimpleDateFormat format = new SimpleDateFormat();
String date = format.format(new Date());
String replacmentString = "Author = "+ getSystemUsername()+ ";" + "Date = "+ date +";]";
int caretOffset = replacmentString.length();
WaypointCompletionProposal proposal = new WaypointCompletionProposal(replacmentString,
replacmentOffset,
replacmentLength,
caretOffset,
getAutoCompleteImage(),
"@tag meta data (Author and date)",
(IContextInformation)null,
"Generate and insert tag meta data (Author and date)");
return proposal;
}
/**
* Simple un commented meta data completion proposal
* @param replacmentOffset
* @param replacmentLength
* @return
*/
private WaypointCompletionProposal createAuthorMetaDataCompletionProposal(int replacmentOffset, int replacmentLength)
{
String replacmentString = "Author = "+ getSystemUsername() +";";
int caretOffset = replacmentString.length();
WaypointCompletionProposal proposal = new WaypointCompletionProposal(replacmentString,
replacmentOffset,
replacmentLength,
caretOffset,
getAutoCompleteImage(),
"@tag Author field",
(IContextInformation)null,
"Generate and insert Author field");
return proposal;
}
/**
* Simple un commented meta data completion proposal
* @param replacmentOffset
* @param replacmentLength
* @return
*/
private WaypointCompletionProposal createDateMetaDataCompletionProposal(int replacmentOffset, int replacmentLength)
{
SimpleDateFormat format = new SimpleDateFormat();
String date = format.format(new Date());
String replacmentString = "Date = "+ date +";]";
int caretOffset = replacmentString.length();
WaypointCompletionProposal proposal = new WaypointCompletionProposal(replacmentString,
replacmentOffset,
replacmentLength,
caretOffset,
getAutoCompleteImage(),
"@tag Date field",
(IContextInformation)null,
"Generate and insert Date field");
return proposal;
}
/**
* Simple tag name completion proposal
* @param replacmentOffset
* @param replacmentLength
* @return
*/
private WaypointCompletionProposal createTagNameCompletionProposal(String tagName,int replacmentOffset, int replacmentLength)
{
String replacmentString = tagName;;
int caretOffset = tagName.length();
WaypointCompletionProposal proposal = new WaypointCompletionProposal(replacmentString,
replacmentOffset,
replacmentLength,
caretOffset,
getAutoCompleteImage(),
tagName,
(IContextInformation)null,
"Insert a java tag");
return proposal;
}
public List computeContextInformation(ContentAssistInvocationContext context, IProgressMonitor monitor) {return null;}
public String getErrorMessage() {return null;}
public void sessionEnded(){}
public void sessionStarted(){}
}