/******************************************************************************* * Copyright (c) 2007-2012 Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is 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 * * Contributor: * Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.common.base.test.contentassist; import java.lang.reflect.Field; import java.util.List; import junit.framework.TestCase; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.contentassist.ContentAssistant; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.text.contentassist.IContentAssistant; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.SourceViewer; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.wst.sse.ui.internal.contentassist.CustomCompletionProposal; import org.jboss.tools.common.text.ext.util.Utils; import org.jboss.tools.test.util.WorkbenchUtils; @SuppressWarnings("restriction") public abstract class AbstractContentAssistantTestCase extends TestCase { protected String fileName; protected IProject project = null; protected IEditorPart editorPart = null; protected ITextEditor textEditor = null; protected ISourceViewer viewer = null; protected IContentAssistant contentAssistant = null; protected IDocument document = null; public void openEditor(String fileName) { this.fileName = fileName; IFile testfile = project.getFile(fileName); // System.out.println(testfile.toString() + ": testfile.exists(): " + testfile.exists() + ", testfile.isAccessible(): " + testfile.isAccessible()); assertTrue("Test file doesn't exist: " + project.getName() + "/" + fileName, (testfile.exists() && testfile.isAccessible())); editorPart = WorkbenchUtils.openEditor(project.getName()+"/"+ fileName); //$NON-NLS-1$ obtainTextEditor(editorPart); viewer = getTextViewer(); document = viewer.getDocument(); // SourceViewerConfiguration config = CATestUtil // .getSourceViewerConfiguration(textEditor); assertNotNull("Cannot get the Source Viewer for the editor for page \"" //$NON-NLS-1$ + fileName + "\"", viewer); //$NON-NLS-1$ contentAssistant = getContentAssistantInternal(); //(config == null ? null : config.getContentAssistant(viewer)); // Fix for JBIDE-12261: Since WTP 3.4 the Content Assistant is made to properly use // autoinsertion property value, so this fact affected the collecting of the proposals // in case of a single proposal is returned if (contentAssistant instanceof ContentAssistant) { ((ContentAssistant) contentAssistant).enableAutoInsert(false); } assertNotNull( "Cannot get the Content Assistant instance for the editor for page \"" //$NON-NLS-1$ + fileName + "\"", contentAssistant); //$NON-NLS-1$ } private IContentAssistant getContentAssistantInternal() { try { Field f = SourceViewer.class.getDeclaredField("fContentAssistant"); f.setAccessible(true); return (IContentAssistant)f.get(viewer); } catch (Exception e) { e.printStackTrace(); } return null; } protected abstract ISourceViewer getTextViewer(); /** * Looks into editorPart for the test editor to apply content assist to. * * @param editorPart */ protected void obtainTextEditor(IEditorPart editorPart) { } public ICompletionProposal[] checkProposals(String fileName, int offset, String[] proposals, boolean exactly) { return checkProposals(fileName, null, offset, proposals, null, exactly, true); } public ICompletionProposal[] checkProposals(String fileName, String substring, int offset, String[] proposals, boolean exactly) { return checkProposals(fileName, substring, offset, proposals, null, exactly, false); } public ICompletionProposal[] checkProposals(String fileName, String substring, int offset, String[] proposals, Image[] images, boolean exactly) { return checkProposals(fileName, substring, offset, proposals, images, exactly, false); } public ICompletionProposal[] checkProposals(String fileName, String substring, int offset, String[] proposals, boolean exactly, boolean excludeELProposalsFromExactTest){ return checkProposals(fileName, substring, offset, proposals, null, exactly, excludeELProposalsFromExactTest); } public ICompletionProposal[] checkProposals(String fileName, String substring, int offset, String[] proposals, Image[] images, boolean exactly, boolean excludeELProposalsFromExactTest){ if(images != null){ assertEquals("number of images and number of proposals must be the same or images must be null", proposals.length, images.length); } openEditor(fileName); assertNotNull("Viewer is not initialized", viewer); assertNotNull("Content Assistant is not initialized", contentAssistant); int position = 0; if (substring != null) { String documentContent = document.get(); position = documentContent.indexOf(substring); } List<ICompletionProposal> res = CATestUtil.collectProposals(contentAssistant, viewer, position+offset); assertTrue("Content Assistant returned no proposals", (res != null && res.size() > 0)); //$NON-NLS-1$ // for (ICompletionProposal p : res) { // System.out.println("proposal - "+p.getDisplayString()); // } ICompletionProposal[] result = res.toArray(new ICompletionProposal[res.size()]); StringBuffer sb = new StringBuffer("["); for (ICompletionProposal p : result) { sb.append(p.getDisplayString()).append("; "); } sb.append("]"); int foundCounter = 0; for (int i = 0; i < proposals.length; i++) { Image image = null; if(images != null){ image = images[i]; } boolean found = compareProposal(proposals[i], image, result); if (found) foundCounter++; assertTrue("Proposal " + proposals[i] + " not found! Found proposals: " + sb.toString(), found ); //$NON-NLS-1$ //$NON-NLS-2$ } if (exactly) { if (excludeELProposalsFromExactTest) { assertEquals("Some other proposals were found! Found proposals: " + sb.toString(), foundCounter, proposals.length); //$NON-NLS-1$ } else { assertEquals("Some other proposals were found! Found proposals: " + sb.toString(), result.length, proposals.length); //$NON-NLS-1$ } } // System.out.println("checkProposals <<< Exiting"); return result; } /** * Returns true if proposal is created by the content assistant being tested. * * @param proposal * @return */ protected boolean isRelevantProposal(ICompletionProposal proposal) { return false; } public boolean compareProposal(String proposalName, Image image, ICompletionProposal[] proposals){ for (int i = 0; i < proposals.length; i++) { if (isRelevantProposal(proposals[i])) { CustomCompletionProposal ap = (CustomCompletionProposal)proposals[i]; String replacementString = ap.getReplacementString().toLowerCase(); if (replacementString.equalsIgnoreCase(proposalName)) return compareImages(image, proposals[i]); // For a tag proposal there will be not only the the tag name but all others characters like default attributes, tag ending characters and so on if (replacementString.indexOf("/>") != -1) { replacementString = replacementString.substring(0, replacementString.indexOf("/>")); } if (replacementString.indexOf('>') != -1) { replacementString = replacementString.substring(0, replacementString.indexOf('>')); } if (replacementString.equalsIgnoreCase(proposalName)) return compareImages(image, proposals[i]); String[] replacementStringParts = replacementString.split(" "); //$NON-NLS-1$ if (replacementStringParts != null && replacementStringParts.length > 0) { if (replacementStringParts[0].equalsIgnoreCase(proposalName)) return compareImages(image, proposals[i]); } // for an attribute proposal there will be a pare of attribute-value (i.e. attrName="attrValue") replacementStringParts = replacementString.split("="); //$NON-NLS-1$ if (replacementStringParts != null && replacementStringParts.length > 0) { if (replacementStringParts[0].equalsIgnoreCase(proposalName)) return compareImages(image, proposals[i]); } // for an Unclosed EL the closing character is appended to the proposal string (i.e. person} ) // perform case insensitive compare operation replacementStringParts = replacementString.split("}"); //$NON-NLS-1$ if (replacementStringParts != null && replacementStringParts.length > 0) { if (replacementStringParts[0].equalsIgnoreCase(proposalName)) return compareImages(image, proposals[i]); } // For an attribute value proposal there will be the quote characters replacementString = Utils.trimQuotes(replacementString); if (replacementString.equalsIgnoreCase(proposalName)) return compareImages(image, proposals[i]); } else { if(proposals[i].getDisplayString().toLowerCase().equals(proposalName.toLowerCase())) return compareImages(image, proposals[i]); } } return false; } private boolean compareImages(Image expected, ICompletionProposal proposal){ if(expected != null){ //System.out.println("<"+proposal.getDisplayString()+"> completion proposal image - "+proposal.getImage()); assertEquals("<"+proposal.getDisplayString()+"> completion proposal returns wrong image", expected, proposal.getImage()); } return true; } public void closeEditor() { if (editorPart != null) { PlatformUI.getWorkbench().getActiveWorkbenchWindow() .getActivePage().closeEditor(editorPart, false); editorPart = null; } viewer = null; document = null; contentAssistant = null; } /** * @return the project */ public IProject getProject() { return project; } /** * @param project the project to set */ public void setProject(IProject project) { this.project = project; } /** * @return the jspTextEditor */ public ITextEditor getTextEditor() { return textEditor; } /** * @return the viewer */ public ISourceViewer getViewer() { return viewer; } /** * @param viewer the viewer to set */ public void setViewer(ISourceViewer viewer) { this.viewer = viewer; } /** * @return the contentAssistant */ public IContentAssistant getContentAssistant() { return contentAssistant; } /** * @param contentAssistant the contentAssistant to set */ public void setContentAssistant(IContentAssistant contentAssistant) { this.contentAssistant = contentAssistant; } /** * @return the document */ public IDocument getDocument() { return document; } /** * @param document the document to set */ public void setDocument(IDocument document) { this.document = document; } }