/******************************************************************************* * Copyright (c) 2005, 2011 IBM Corporation and others. * 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.wst.jsdt.internal.ui.text.java; import java.util.ArrayList; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.wst.jsdt.core.CompletionProposal; import org.eclipse.wst.jsdt.core.IField; import org.eclipse.wst.jsdt.core.IJavaScriptElement; import org.eclipse.wst.jsdt.core.IJavaScriptProject; import org.eclipse.wst.jsdt.core.ILocalVariable; import org.eclipse.wst.jsdt.core.IMember; import org.eclipse.wst.jsdt.core.IType; import org.eclipse.wst.jsdt.core.JavaScriptModelException; import org.eclipse.wst.jsdt.core.search.IJavaScriptSearchScope; import org.eclipse.wst.jsdt.core.search.SearchEngine; import org.eclipse.wst.jsdt.core.search.SearchMatch; import org.eclipse.wst.jsdt.core.search.SearchParticipant; import org.eclipse.wst.jsdt.core.search.SearchPattern; import org.eclipse.wst.jsdt.core.search.SearchRequestor; import org.eclipse.wst.jsdt.internal.core.DefaultWorkingCopyOwner; import org.eclipse.wst.jsdt.internal.core.search.matching.FieldPattern; import org.eclipse.wst.jsdt.internal.core.util.QualificationHelpers; import org.eclipse.wst.jsdt.internal.corext.template.java.SignatureUtil; import org.eclipse.wst.jsdt.internal.ui.Logger; /** * Proposal info that computes the javadoc lazily when it is queried. * * */ public final class FieldProposalInfo extends MemberProposalInfo { /** * Creates a new proposal info. * * @param project the java project to reference when resolving types * @param proposal the proposal to generate information for */ public FieldProposalInfo(IJavaScriptProject project, CompletionProposal proposal) { super(project, proposal); } /** * <p>Returns the java element that this computer corresponds to, possibly <code>null</code>.</p> * * <p><b>NOTE:</b> This overrides the parent implementation so that {@link #resolveMember()} is not called * because the field proposal can resolve to a none {@link IMember}.</p> * * @return the java element that this computer corresponds to, possibly <code>null</code> * @throws JavaScriptModelException */ public IJavaScriptElement getJavaElement() throws JavaScriptModelException { if (!fJavaElementResolved) { fJavaElementResolved= true; //call the internal resolve rather then #resolveMember fElement = resolve(); } return fElement; } /** * @see org.eclipse.wst.jsdt.internal.ui.text.java.MemberProposalInfo#resolveMember() */ protected IMember resolveMember() throws JavaScriptModelException { IMember member = null; IJavaScriptElement element = this.resolve(); if(element instanceof IMember) { member = (IMember)element; } return member; } /** * @return {@link IJavaScriptElement} that this field proposal resolves to * * @throws JavaScriptModelException */ private IJavaScriptElement resolve() throws JavaScriptModelException { //get the type name char[] typeNameChars = fProposal.getDeclarationTypeName(); String declaringTypeName = null; if(typeNameChars != null) { declaringTypeName = String.valueOf(typeNameChars); } /* try using the signature if type name not set * NOTE: old way of doing things, should be removed at some point */ if(declaringTypeName == null) { char[] declarationSignature= fProposal.getDeclarationSignature(); if(declarationSignature != null) { declaringTypeName = SignatureUtil.stripSignatureToFQN(String.valueOf(declarationSignature)); } } //find the field IJavaScriptElement resolvedField = null; if(declaringTypeName != null) { String fieldName = String.valueOf(fProposal.getName()); IType[] types = this.fJavaProject.findTypes(declaringTypeName); if(types != null && types.length > 0) { for(int i = 0; i < types.length && resolvedField == null; ++i) { IType type = types[i]; if (type != null) { IField field = type.getField(fieldName); if (field.exists()) { resolvedField = field; } } } } else { //create the search pattern char[][] seperatedDeclaringTypename = QualificationHelpers.seperateFullyQualifedName(declaringTypeName.toCharArray()); // if(!CharOperation.equals(seperatedDeclaringTypename[QualificationHelpers.SIMPLE_NAMES_INDEX], IIndexConstants.GLOBAL_SYMBOL)) { FieldPattern fieldPattern = new FieldPattern(true, false, false, fieldName.toCharArray(), seperatedDeclaringTypename[QualificationHelpers.QULIFIERS_INDEX], seperatedDeclaringTypename[QualificationHelpers.SIMPLE_NAMES_INDEX], SearchPattern.R_EXACT_MATCH); //search the index for a match SearchEngine searchEngine = new SearchEngine(DefaultWorkingCopyOwner.PRIMARY); IJavaScriptSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaScriptElement[] {this.fJavaProject}); final List matches = new ArrayList(); try { searchEngine.search(fieldPattern, new SearchParticipant[] {SearchEngine.getDefaultSearchParticipant()}, scope, new SearchRequestor() { public void acceptSearchMatch(SearchMatch match) throws CoreException { Object element = match.getElement(); if(element instanceof IField || element instanceof ILocalVariable) { matches.add(element); } } }, new NullProgressMonitor()); //using a NPM here maybe a bad idea, but nothing better to do right now } catch (CoreException e) { Logger.logException("Failed index search for field: " + fieldName, e); //$NON-NLS-1$ } // just use the first match found if(!matches.isEmpty()) { resolvedField = (IJavaScriptElement)matches.get(0); } // } } } return resolvedField; } }