/* * Copyright (c) 2010-2012 Research In Motion Limited. All rights reserved. * * This program and the accompanying materials are made available * under the terms of the Eclipse Public License, Version 1.0, * which accompanies this distribution and is available at * * http://www.eclipse.org/legal/epl-v10.html * */ package net.rim.ejde.internal.codeassisstant; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.rim.ejde.internal.builders.PreprocessingBuilder; import net.rim.ejde.internal.core.ContextManager; import net.rim.ejde.internal.core.IConstants; import net.rim.ejde.internal.model.BlackBerryProject; import net.rim.ejde.internal.model.BlackBerryProperties; import net.rim.ejde.internal.model.BlackBerrySDKInstall; import net.rim.ejde.internal.util.Messages; import net.rim.ejde.internal.util.VMUtils; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.launching.IVMInstall; import org.eclipse.jdt.ui.text.java.ContentAssistInvocationContext; import org.eclipse.jdt.ui.text.java.IJavaCompletionProposalComputer; import org.eclipse.jdt.ui.text.java.JavaContentAssistInvocationContext; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.text.contentassist.IContextInformation; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.plugin.AbstractUIPlugin; /** * This class is used to computer the code completion proposals for preprocess defines. Basically, when a user type "//#ifdef" and * then press Ctrl + Space, all preprocess directives are popped up for the user to choose. * * * */ public class PreprocessDirectiveCompletionProposalComputer implements IJavaCompletionProposalComputer { static Logger _log = Logger.getLogger( PreprocessDirectiveCompletionProposalComputer.class ); static private final String BASIC_PREPROCESS_DIRECTIVE_PROPOSAL_PATTERN = "\\s*?//#ifdef\\s+.*"; Image _preprocessImage; public PreprocessDirectiveCompletionProposalComputer() { // TODO Auto-generated constructor stub } public List< ICompletionProposal > computeCompletionProposals( ContentAssistInvocationContext context, IProgressMonitor monitor ) { List< ICompletionProposal > proposals = new ArrayList< ICompletionProposal >(); if( !( context instanceof JavaContentAssistInvocationContext ) ) { return proposals; } JavaContentAssistInvocationContext javaContext = (JavaContentAssistInvocationContext) context; IJavaProject javaProject = javaContext.getProject(); int offset = javaContext.getCoreContext().getOffset(); IDocument doc = javaContext.getDocument(); String lineContent; IRegion line = null; Pattern p = Pattern.compile( BASIC_PREPROCESS_DIRECTIVE_PROPOSAL_PATTERN ); try { line = doc.getLineInformationOfOffset( offset ); int length = offset > line.getOffset() ? offset - line.getOffset() : 0; lineContent = doc.get( line.getOffset(), length ); Matcher matcher = p.matcher( lineContent ); // check if it matches the basic pattern if( matcher.matches() ) { proposals = getProposals( javaProject, offset, lineContent ); } } catch( BadLocationException e ) { _log.error( e ); } return proposals; } @Override public List< IContextInformation > computeContextInformation( ContentAssistInvocationContext context, IProgressMonitor monitor ) { // TODO Auto-generated method stub return null; } @Override public String getErrorMessage() { // TODO Auto-generated method stub return null; } @Override public void sessionEnded() { // nothing need to be done here } @Override public void sessionStarted() { // nothing need to be done here } private List< ICompletionProposal > getProposals( IJavaProject javaProject, int offset, String content ) { List< IVMInstall > vmList = VMUtils.getInstalledBBVMs(); Collections.sort( vmList, new VMUtils.VMGeneralComparator() ); List< ICompletionProposal > proposalList = new ArrayList< ICompletionProposal >( vmList.size() ); PreprocessDirectiveCompletionProposal proposal = null; BlackBerrySDKInstall bbVM; String directive; String directivePrefix; int indexOfLastSpace = content.lastIndexOf( IConstants.ONE_BLANK_STRING ); // indexOfLastSpace can never be negative // get proposals for CP level pre-defined preprocess directives for( int i = 0; i < vmList.size(); i++ ) { bbVM = (BlackBerrySDKInstall) vmList.get( i ); directive = VMUtils.getJREDirective( bbVM ); if( StringUtils.isBlank( directive ) ) { continue; } directivePrefix = content.substring( indexOfLastSpace + 1, content.length() ); proposal = createProposal( directivePrefix, directive, offset - directivePrefix.length(), getPreprocessDefineImage(), directive, NLS.bind( Messages.PREDEFINED_PREPROCESS_DEFINE_INFO, directive ) ); if( proposal != null ) { proposalList.add( proposal ); } } // get proposals for workspace level and project level preprocess directives BlackBerryProperties properties = ContextManager.PLUGIN.getBBProperties( javaProject.getProject().getName(), false ); List< String > directives = PreprocessingBuilder.getDefines( new BlackBerryProject( javaProject, properties ), false ); for( int i = 0; i < directives.size(); i++ ) { directive = directives.get( i ); directivePrefix = content.substring( indexOfLastSpace + 1, content.length() ); proposal = createProposal( directivePrefix, directive, offset - directivePrefix.length(), getPreprocessDefineImage(), directive, Messages.CUSTOMIZED_PREPROCESS_DEFINE_INFO ); if( proposal != null && !proposalList.contains(proposal)) { proposalList.add( proposal ); } } return proposalList; } private PreprocessDirectiveCompletionProposal createProposal( String prefix, String define, int offset, Image image, String displayString, String otherInfo ) { PreprocessDirectiveCompletionProposal proposal = null; if( define.toLowerCase().startsWith( prefix.toLowerCase() ) ) { proposal = new PreprocessDirectiveCompletionProposal( define, offset, 0, define.length(), image, define, null, otherInfo ); } return proposal; } public Image getPreprocessDefineImage() { if( _preprocessImage == null ) { ImageDescriptor imageDescriptor = AbstractUIPlugin.imageDescriptorFromPlugin( ContextManager.PLUGIN_ID, "icons" + File.separator + "bb_perspective.gif" ); _preprocessImage = imageDescriptor.createImage(); } return _preprocessImage; } public void dispose() { if( _preprocessImage != null ) { _preprocessImage.dispose(); } } }