0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041:
0042: package org.netbeans.modules.editor.java;
0043:
0044: import com.sun.source.tree.*;
0045: import com.sun.source.util.SourcePositions;
0046: import com.sun.source.util.TreePath;
0047: import com.sun.source.util.Trees;
0048: import java.awt.Color;
0049: import java.awt.Font;
0050: import java.awt.Graphics;
0051: import java.awt.event.KeyEvent;
0052: import java.io.IOException;
0053: import java.util.*;
0054: import java.util.logging.Level;
0055: import java.util.logging.Logger;
0056: import javax.lang.model.element.*;
0057: import javax.lang.model.type.*;
0058: import javax.lang.model.util.ElementFilter;
0059: import javax.lang.model.util.Elements;
0060: import javax.swing.ImageIcon;
0061: import javax.swing.SwingUtilities;
0062: import javax.swing.text.BadLocationException;
0063: import javax.swing.text.JTextComponent;
0064: import javax.swing.text.Position;
0065: import org.netbeans.api.editor.completion.Completion;
0066: import org.netbeans.api.java.lexer.JavaTokenId;
0067: import org.netbeans.api.java.source.*;
0068: import org.netbeans.api.java.source.JavaSource.Phase;
0069: import org.netbeans.api.lexer.TokenHierarchy;
0070: import org.netbeans.api.lexer.TokenSequence;
0071: import org.netbeans.editor.BaseDocument;
0072: import org.netbeans.lib.editor.codetemplates.api.CodeTemplateManager;
0073: import org.netbeans.modules.java.editor.codegen.GeneratorUtils;
0074: import org.netbeans.spi.editor.completion.CompletionItem;
0075: import org.netbeans.spi.editor.completion.CompletionTask;
0076: import org.netbeans.spi.editor.completion.support.CompletionUtilities;
0077: import org.openide.util.NbBundle;
0078: import org.openide.xml.XMLUtil;
0079:
0080: /**
0081: *
0082: * @author Dusan Balek
0083: */
0084: public abstract class JavaCompletionItem implements CompletionItem {
0085:
0086: protected static int SMART_TYPE = 1000;
0087: private static final String GENERATE_TEXT = NbBundle.getMessage(
0088: JavaCompletionItem.class, "generate_Lbl");
0089:
0090: public static final JavaCompletionItem createKeywordItem(
0091: String kwd, String postfix, int substitutionOffset,
0092: boolean smartType) {
0093: return new KeywordItem(kwd, 0, postfix, substitutionOffset,
0094: smartType);
0095: }
0096:
0097: public static final JavaCompletionItem createPackageItem(
0098: String pkgFQN, int substitutionOffset, boolean isDeprecated) {
0099: return new PackageItem(pkgFQN, substitutionOffset, isDeprecated);
0100: }
0101:
0102: public static final JavaCompletionItem createTypeItem(
0103: TypeElement elem, DeclaredType type,
0104: int substitutionOffset, boolean displayPkgName,
0105: boolean isDeprecated, boolean insideNew, boolean smartType) {
0106: switch (elem.getKind()) {
0107: case CLASS:
0108: return new ClassItem(elem, type, 0, substitutionOffset,
0109: displayPkgName, isDeprecated, insideNew, smartType);
0110: case INTERFACE:
0111: return new InterfaceItem(elem, type, 0, substitutionOffset,
0112: displayPkgName, isDeprecated, insideNew, smartType);
0113: case ENUM:
0114: return new EnumItem(elem, type, 0, substitutionOffset,
0115: displayPkgName, isDeprecated, insideNew, smartType);
0116: case ANNOTATION_TYPE:
0117: return new AnnotationTypeItem(elem, type, 0,
0118: substitutionOffset, displayPkgName, isDeprecated,
0119: insideNew, smartType);
0120: default:
0121: throw new IllegalArgumentException("kind=" + elem.getKind());
0122: }
0123: }
0124:
0125: public static final JavaCompletionItem createArrayItem(
0126: ArrayType type, int substitutionOffset, Elements elements) {
0127: int dim = 0;
0128: TypeMirror tm = type;
0129: while (tm.getKind() == TypeKind.ARRAY) {
0130: tm = ((ArrayType) tm).getComponentType();
0131: dim++;
0132: }
0133: if (tm.getKind().isPrimitive())
0134: return new KeywordItem(tm.toString(), dim, null,
0135: substitutionOffset, true);
0136: if (tm.getKind() == TypeKind.DECLARED
0137: || tm.getKind() == TypeKind.ERROR) {
0138: DeclaredType dt = (DeclaredType) tm;
0139: TypeElement elem = (TypeElement) dt.asElement();
0140: switch (elem.getKind()) {
0141: case CLASS:
0142: return new ClassItem(elem, dt, dim, substitutionOffset,
0143: true, elements.isDeprecated(elem), false, true);
0144: case INTERFACE:
0145: return new InterfaceItem(elem, dt, dim,
0146: substitutionOffset, true, elements
0147: .isDeprecated(elem), false, true);
0148: case ENUM:
0149: return new EnumItem(elem, dt, dim, substitutionOffset,
0150: true, elements.isDeprecated(elem), false, true);
0151: case ANNOTATION_TYPE:
0152: return new AnnotationTypeItem(elem, dt, dim,
0153: substitutionOffset, true, elements
0154: .isDeprecated(elem), false, true);
0155: }
0156: }
0157: throw new IllegalArgumentException("array element kind="
0158: + tm.getKind());
0159: }
0160:
0161: public static final JavaCompletionItem createTypeParameterItem(
0162: TypeParameterElement elem, int substitutionOffset) {
0163: return new TypeParameterItem(elem, substitutionOffset);
0164: }
0165:
0166: public static final JavaCompletionItem createVariableItem(
0167: VariableElement elem, TypeMirror type,
0168: int substitutionOffset, boolean isInherited,
0169: boolean isDeprecated, boolean smartType) {
0170: switch (elem.getKind()) {
0171: case LOCAL_VARIABLE:
0172: case PARAMETER:
0173: case EXCEPTION_PARAMETER:
0174: return new VariableItem(type, elem.getSimpleName()
0175: .toString(), substitutionOffset, smartType);
0176: case ENUM_CONSTANT:
0177: case FIELD:
0178: return new FieldItem(elem, type, substitutionOffset,
0179: isInherited, isDeprecated, smartType);
0180: default:
0181: throw new IllegalArgumentException("kind=" + elem.getKind());
0182: }
0183: }
0184:
0185: public static final JavaCompletionItem createVariableItem(
0186: String varName, int substitutionOffset, boolean smartType) {
0187: return new VariableItem(null, varName, substitutionOffset,
0188: smartType);
0189: }
0190:
0191: public static final JavaCompletionItem createExecutableItem(
0192: ExecutableElement elem, ExecutableType type,
0193: int substitutionOffset, boolean isInherited,
0194: boolean isDeprecated, boolean inImport, boolean smartType) {
0195: switch (elem.getKind()) {
0196: case METHOD:
0197: return new MethodItem(elem, type, substitutionOffset,
0198: isInherited, isDeprecated, inImport, smartType);
0199: case CONSTRUCTOR:
0200: return new ConstructorItem(elem, type, substitutionOffset,
0201: isDeprecated, smartType);
0202: default:
0203: throw new IllegalArgumentException("kind=" + elem.getKind());
0204: }
0205: }
0206:
0207: public static final JavaCompletionItem createOverrideMethodItem(
0208: ExecutableElement elem, ExecutableType type,
0209: int substitutionOffset, boolean implement) {
0210: switch (elem.getKind()) {
0211: case METHOD:
0212: return new OverrideMethodItem(elem, type,
0213: substitutionOffset, implement);
0214: default:
0215: throw new IllegalArgumentException("kind=" + elem.getKind());
0216: }
0217: }
0218:
0219: public static final JavaCompletionItem createGetterSetterMethodItem(
0220: VariableElement elem, TypeMirror type,
0221: int substitutionOffset, boolean setter) {
0222: switch (elem.getKind()) {
0223: case ENUM_CONSTANT:
0224: case FIELD:
0225: return new GetterSetterMethodItem(elem, type,
0226: substitutionOffset, setter);
0227: default:
0228: throw new IllegalArgumentException("kind=" + elem.getKind());
0229: }
0230: }
0231:
0232: public static final JavaCompletionItem createDefaultConstructorItem(
0233: TypeElement elem, int substitutionOffset, boolean smartType) {
0234: return new DefaultConstructorItem(elem, substitutionOffset,
0235: smartType);
0236: }
0237:
0238: public static final JavaCompletionItem createParametersItem(
0239: ExecutableElement elem, ExecutableType type,
0240: int substitutionOffset, boolean isDeprecated,
0241: int activeParamIndex) {
0242: return new ParametersItem(elem, type, substitutionOffset,
0243: isDeprecated, activeParamIndex);
0244: }
0245:
0246: public static final JavaCompletionItem createAnnotationItem(
0247: TypeElement elem, DeclaredType type,
0248: int substitutionOffset, boolean isDeprecated) {
0249: return new AnnotationItem(elem, type, substitutionOffset,
0250: isDeprecated, true);
0251: }
0252:
0253: public static final JavaCompletionItem createAttributeItem(
0254: ExecutableElement elem, ExecutableType type,
0255: int substitutionOffset, boolean isDeprecated) {
0256: return new AttributeItem(elem, type, substitutionOffset,
0257: isDeprecated);
0258: }
0259:
0260: public static final JavaCompletionItem createStaticMemberItem(
0261: DeclaredType type, Element memberElem,
0262: TypeMirror memberType, int substitutionOffset,
0263: boolean isDeprecated) {
0264: switch (memberElem.getKind()) {
0265: case METHOD:
0266: case ENUM_CONSTANT:
0267: case FIELD:
0268: return new StaticMemberItem(type, memberElem, memberType,
0269: substitutionOffset, isDeprecated);
0270: default:
0271: throw new IllegalArgumentException("kind="
0272: + memberElem.getKind());
0273: }
0274: }
0275:
0276: public static final JavaCompletionItem createInitializeAllConstructorItem(
0277: Iterable<? extends VariableElement> fields,
0278: TypeElement parent, int substitutionOffset) {
0279: return new InitializeAllConstructorItem(fields, parent,
0280: substitutionOffset);
0281: }
0282:
0283: public static final String COLOR_END = "</font>"; //NOI18N
0284: public static final String STRIKE = "<s>"; //NOI18N
0285: public static final String STRIKE_END = "</s>"; //NOI18N
0286: public static final String BOLD = "<b>"; //NOI18N
0287: public static final String BOLD_END = "</b>"; //NOI18N
0288:
0289: protected int substitutionOffset;
0290:
0291: protected JavaCompletionItem(int substitutionOffset) {
0292: this .substitutionOffset = substitutionOffset;
0293: }
0294:
0295: public void defaultAction(JTextComponent component) {
0296: if (component != null) {
0297: Completion.get().hideDocumentation();
0298: Completion.get().hideCompletion();
0299: int caretOffset = component.getSelectionEnd();
0300: substituteText(component, substitutionOffset, caretOffset
0301: - substitutionOffset, null);
0302: }
0303: }
0304:
0305: public void processKeyEvent(KeyEvent evt) {
0306: if (evt.getID() == KeyEvent.KEY_TYPED) {
0307: switch (evt.getKeyChar()) {
0308: case ':':
0309: case ';':
0310: case ',':
0311: case '(':
0312: Completion.get().hideDocumentation();
0313: Completion.get().hideCompletion();
0314: JTextComponent component = (JTextComponent) evt
0315: .getSource();
0316: int caretOffset = component.getSelectionEnd();
0317: substituteText(component, substitutionOffset,
0318: caretOffset - substitutionOffset, Character
0319: .toString(evt.getKeyChar()));
0320: evt.consume();
0321: break;
0322: case '.':
0323: Completion.get().hideDocumentation();
0324: component = (JTextComponent) evt.getSource();
0325: caretOffset = component.getSelectionEnd();
0326: substituteText(component, substitutionOffset,
0327: caretOffset - substitutionOffset, Character
0328: .toString(evt.getKeyChar()));
0329: evt.consume();
0330: caretOffset = component.getSelectionEnd();
0331: try {
0332: if (caretOffset > 0
0333: && !".".equals(component.getDocument()
0334: .getText(caretOffset - 1, 1))) {
0335: Completion.get().hideCompletion();
0336: break;
0337: }
0338: } catch (BadLocationException ble) {
0339: }
0340: Completion.get().showCompletion();
0341: break;
0342: }
0343: }
0344: }
0345:
0346: public boolean instantSubstitution(JTextComponent component) {
0347: if (component != null) {
0348: try {
0349: int caretOffset = component.getSelectionEnd();
0350: if (caretOffset > substitutionOffset) {
0351: String text = component.getDocument().getText(
0352: substitutionOffset,
0353: caretOffset - substitutionOffset);
0354: if (!getInsertPrefix().toString().startsWith(text)) {
0355: return false;
0356: }
0357: }
0358: } catch (BadLocationException ble) {
0359: }
0360: }
0361: defaultAction(component);
0362: return true;
0363: }
0364:
0365: public CompletionTask createDocumentationTask() {
0366: return null;
0367: }
0368:
0369: public CompletionTask createToolTipTask() {
0370: return null;
0371: }
0372:
0373: public int getPreferredWidth(Graphics g, Font defaultFont) {
0374: return CompletionUtilities.getPreferredWidth(getLeftHtmlText(),
0375: getRightHtmlText(), g, defaultFont);
0376: }
0377:
0378: public void render(Graphics g, Font defaultFont,
0379: Color defaultColor, Color backgroundColor, int width,
0380: int height, boolean selected) {
0381: CompletionUtilities.renderHtml(getIcon(), getLeftHtmlText(),
0382: getRightHtmlText(), g, defaultFont, defaultColor,
0383: width, height, selected);
0384: }
0385:
0386: protected ImageIcon getIcon() {
0387: return null;
0388: }
0389:
0390: protected String getLeftHtmlText() {
0391: return null;
0392: }
0393:
0394: protected String getRightHtmlText() {
0395: return null;
0396: }
0397:
0398: protected void substituteText(JTextComponent c, int offset,
0399: int len, String toAdd) {
0400: BaseDocument doc = (BaseDocument) c.getDocument();
0401: CharSequence prefix = getInsertPrefix();
0402: if (prefix == null)
0403: return;
0404: StringBuilder text = new StringBuilder(prefix);
0405: boolean completeMethod = text.length() == len && toAdd != null
0406: && "()".equals(toAdd.trim());
0407: int semiPos = toAdd != null && toAdd.endsWith(";") ? findPositionForSemicolon(c)
0408: : -2; //NOI18N
0409: if (semiPos > -2)
0410: toAdd = toAdd.length() > 1 ? toAdd.substring(0, toAdd
0411: .length() - 1) : null;
0412: if (toAdd != null && !toAdd.equals("\n")) {//NOI18N
0413: char ch;
0414: int i = 0;
0415: while (i < toAdd.length() && (ch = toAdd.charAt(i)) <= ' ') {
0416: text.append(ch);
0417: i++;
0418: }
0419: if (i > 0)
0420: toAdd = toAdd.substring(i);
0421: TokenSequence<JavaTokenId> sequence = SourceUtils
0422: .getJavaTokenSequence(TokenHierarchy.get(doc),
0423: offset + len);
0424: if (sequence == null || !sequence.moveNext()
0425: && !sequence.movePrevious()) {
0426: text.append(toAdd);
0427: toAdd = null;
0428: }
0429: boolean added = false;
0430: while (toAdd != null && toAdd.length() > 0) {
0431: String tokenText = sequence.token().text().toString();
0432: if (tokenText.startsWith(toAdd)) {
0433: len = sequence.offset() - offset + toAdd.length();
0434: text.append(toAdd);
0435: toAdd = null;
0436: } else if (toAdd.startsWith(tokenText)) {
0437: sequence.moveNext();
0438: len = sequence.offset() - offset;
0439: text.append(toAdd.substring(0, tokenText.length()));
0440: toAdd = toAdd.substring(tokenText.length());
0441: added = true;
0442: } else if (sequence.token().id() == JavaTokenId.WHITESPACE
0443: && sequence.token().text().toString().indexOf(
0444: '\n') < 0) {//NOI18N
0445: if (!sequence.moveNext()) {
0446: text.append(toAdd);
0447: toAdd = null;
0448: }
0449: } else {
0450: if (!added)
0451: text.append(toAdd);
0452: toAdd = null;
0453: }
0454: }
0455: }
0456: // Update the text
0457: doc.atomicLock();
0458: try {
0459: String textToReplace = doc.getText(offset, len);
0460: if (textToReplace.contentEquals(text)) {
0461: if (semiPos > -1)
0462: doc.insertString(semiPos, ";", null); //NOI18N
0463: return;
0464: }
0465: Position position = doc.createPosition(offset);
0466: Position semiPosition = semiPos > -1 ? doc
0467: .createPosition(semiPos) : null;
0468: doc.remove(offset, len);
0469: doc.insertString(position.getOffset(), text.toString(),
0470: null);
0471: if (semiPosition != null)
0472: doc.insertString(semiPosition.getOffset(), ";", null);
0473: else if (completeMethod)
0474: c.setCaretPosition(c.getCaretPosition() - 1);
0475: } catch (BadLocationException e) {
0476: // Can't update
0477: } finally {
0478: doc.atomicUnlock();
0479: }
0480: }
0481:
0482: static class KeywordItem extends JavaCompletionItem {
0483:
0484: private static final String JAVA_KEYWORD = "org/netbeans/modules/java/editor/resources/javakw_16.png"; //NOI18N
0485: private static final String KEYWORD_COLOR = "<font color=#000099>"; //NOI18N
0486: private static ImageIcon icon;
0487:
0488: private String kwd;
0489: private int dim;
0490: private String postfix;
0491: private boolean smartType;
0492: private String leftText;
0493:
0494: private KeywordItem(String kwd, int dim, String postfix,
0495: int substitutionOffset, boolean smartType) {
0496: super (substitutionOffset);
0497: this .kwd = kwd;
0498: this .dim = dim;
0499: this .postfix = postfix;
0500: this .smartType = smartType;
0501: }
0502:
0503: public int getSortPriority() {
0504: return smartType ? 600 - SMART_TYPE : 600;
0505: }
0506:
0507: public CharSequence getSortText() {
0508: return kwd;
0509: }
0510:
0511: public CharSequence getInsertPrefix() {
0512: return kwd;
0513: }
0514:
0515: protected ImageIcon getIcon() {
0516: if (icon == null)
0517: icon = new ImageIcon(org.openide.util.Utilities
0518: .loadImage(JAVA_KEYWORD));
0519: return icon;
0520: }
0521:
0522: protected String getLeftHtmlText() {
0523: if (leftText == null) {
0524: StringBuilder sb = new StringBuilder();
0525: sb.append(KEYWORD_COLOR);
0526: sb.append(BOLD);
0527: sb.append(kwd);
0528: for (int i = 0; i < dim; i++)
0529: sb.append("[]"); //NOI18N
0530: sb.append(BOLD_END);
0531: sb.append(COLOR_END);
0532: leftText = sb.toString();
0533: }
0534: return leftText;
0535: }
0536:
0537: protected void substituteText(JTextComponent c, int offset,
0538: int len, String toAdd) {
0539: if (dim == 0) {
0540: super .substituteText(c, offset, len,
0541: toAdd != null ? toAdd : postfix);
0542: return;
0543: }
0544: BaseDocument doc = (BaseDocument) c.getDocument();
0545: final StringBuilder text = new StringBuilder();
0546: int semiPos = toAdd != null && toAdd.endsWith(";") ? findPositionForSemicolon(c)
0547: : -2; //NOI18N
0548: if (semiPos > -2)
0549: toAdd = toAdd.length() > 1 ? toAdd.substring(0, toAdd
0550: .length() - 1) : null;
0551: if (toAdd != null && !toAdd.equals("\n")) {//NOI18N
0552: TokenSequence<JavaTokenId> sequence = SourceUtils
0553: .getJavaTokenSequence(TokenHierarchy.get(doc),
0554: offset + len);
0555: if (sequence == null || !sequence.moveNext()
0556: && !sequence.movePrevious()) {
0557: text.append(toAdd);
0558: toAdd = null;
0559: }
0560: boolean added = false;
0561: while (toAdd != null && toAdd.length() > 0) {
0562: String tokenText = sequence.token().text()
0563: .toString();
0564: if (tokenText.startsWith(toAdd)) {
0565: len = sequence.offset() - offset
0566: + toAdd.length();
0567: text.append(toAdd);
0568: toAdd = null;
0569: } else if (toAdd.startsWith(tokenText)) {
0570: sequence.moveNext();
0571: len = sequence.offset() - offset;
0572: text.append(toAdd.substring(0, tokenText
0573: .length()));
0574: toAdd = toAdd.substring(tokenText.length());
0575: added = true;
0576: } else if (sequence.token().id() == JavaTokenId.WHITESPACE
0577: && sequence.token().text().toString()
0578: .indexOf('\n') < 0) {//NOI18N
0579: if (!sequence.moveNext()) {
0580: text.append(toAdd);
0581: toAdd = null;
0582: }
0583: } else {
0584: if (!added)
0585: text.append(toAdd);
0586: toAdd = null;
0587: }
0588: }
0589: }
0590: StringBuilder sb = new StringBuilder();
0591: int cnt = 1;
0592: sb.append(kwd);
0593: for (int i = 0; i < dim; i++) {
0594: sb.append("[${PAR"); //NOI18N
0595: sb.append(cnt++);
0596: sb.append(" instanceof=\"int\" default=\"\"}]"); //NOI18N
0597: }
0598: doc.atomicLock();
0599: try {
0600: Position semiPosition = semiPos > -1 ? doc
0601: .createPosition(semiPos) : null;
0602: if (len > 0)
0603: doc.remove(offset, len);
0604: if (semiPosition != null)
0605: doc.insertString(semiPosition.getOffset(), ";",
0606: null); //NOI18N
0607: } catch (BadLocationException e) {
0608: // Can't update
0609: } finally {
0610: doc.atomicUnlock();
0611: }
0612: CodeTemplateManager ctm = CodeTemplateManager.get(doc);
0613: if (ctm != null) {
0614: ctm.createTemporary(sb.append(text).toString()).insert(
0615: c);
0616: }
0617: }
0618:
0619: public String toString() {
0620: return kwd;
0621: }
0622: }
0623:
0624: static class PackageItem extends JavaCompletionItem {
0625:
0626: private static final String PACKAGE = "org/netbeans/modules/java/editor/resources/package.gif"; // NOI18N
0627: private static final String PACKAGE_COLOR = "<font color=#005600>"; //NOI18N
0628: private static ImageIcon icon;
0629:
0630: private boolean isDeprecated;
0631: private String simpleName;
0632: private String sortText;
0633: private String leftText;
0634:
0635: private PackageItem(String pkgFQN, int substitutionOffset,
0636: boolean isDeprecated) {
0637: super (substitutionOffset);
0638: this .isDeprecated = isDeprecated;
0639: int idx = pkgFQN.lastIndexOf('.');
0640: this .simpleName = idx < 0 ? pkgFQN : pkgFQN
0641: .substring(idx + 1);
0642: this .sortText = this .simpleName + "#" + pkgFQN; //NOI18N
0643: }
0644:
0645: public int getSortPriority() {
0646: return 900;
0647: }
0648:
0649: public CharSequence getSortText() {
0650: return sortText;
0651: }
0652:
0653: public CharSequence getInsertPrefix() {
0654: return simpleName;
0655: }
0656:
0657: protected ImageIcon getIcon() {
0658: if (icon == null)
0659: icon = new ImageIcon(org.openide.util.Utilities
0660: .loadImage(PACKAGE));
0661: return icon;
0662: }
0663:
0664: protected String getLeftHtmlText() {
0665: if (leftText == null) {
0666: StringBuilder sb = new StringBuilder();
0667: sb.append(PACKAGE_COLOR);
0668: if (isDeprecated)
0669: sb.append(STRIKE);
0670: sb.append(simpleName);
0671: if (isDeprecated)
0672: sb.append(STRIKE_END);
0673: sb.append(COLOR_END);
0674: leftText = sb.toString();
0675: }
0676: return leftText;
0677: }
0678:
0679: public String toString() {
0680: return simpleName;
0681: }
0682: }
0683:
0684: static class ClassItem extends JavaCompletionItem {
0685:
0686: private static final String CLASS = "org/netbeans/modules/editor/resources/completion/class_16.png"; //NOI18N
0687: private static final String CLASS_COLOR = "<font color=#560000>"; //NOI18N
0688: private static final String PKG_COLOR = "<font color=#808080>"; //NOI18N
0689: private static ImageIcon icon;
0690:
0691: protected TypeMirrorHandle<DeclaredType> typeHandle;
0692: private int dim;
0693: private boolean isDeprecated;
0694: private boolean insideNew;
0695: private boolean smartType;
0696: private String simpleName;
0697: private String typeName;
0698: private String enclName;
0699: private CharSequence sortText;
0700: private String leftText;
0701:
0702: private ClassItem(TypeElement elem, DeclaredType type, int dim,
0703: int substitutionOffset, boolean displayPkgName,
0704: boolean isDeprecated, boolean insideNew,
0705: boolean smartType) {
0706: super (substitutionOffset);
0707: this .typeHandle = TypeMirrorHandle.create(type);
0708: this .dim = dim;
0709: this .isDeprecated = isDeprecated;
0710: this .insideNew = insideNew;
0711: this .smartType = smartType;
0712: this .simpleName = elem.getSimpleName().toString();
0713: this .typeName = Utilities.getTypeName(type, false)
0714: .toString();
0715: if (displayPkgName) {
0716: this .enclName = Utilities.getElementName(
0717: elem.getEnclosingElement(), true).toString();
0718: this .sortText = this .simpleName
0719: + Utilities.getImportanceLevel(this .enclName)
0720: + "#" + this .enclName; //NOI18N
0721:
0722: } else {
0723: this .enclName = null;
0724: this .sortText = this .simpleName;
0725: }
0726: }
0727:
0728: public int getSortPriority() {
0729: return smartType ? 800 - SMART_TYPE : 800;
0730: }
0731:
0732: public CharSequence getSortText() {
0733: return sortText;
0734: }
0735:
0736: public CharSequence getInsertPrefix() {
0737: return simpleName;
0738: }
0739:
0740: public boolean instantSubstitution(JTextComponent component) {
0741: return false;
0742: }
0743:
0744: public CompletionTask createDocumentationTask() {
0745: return typeHandle.getKind() == TypeKind.DECLARED ? JavaCompletionProvider
0746: .createDocTask(ElementHandle.from(typeHandle))
0747: : null;
0748: }
0749:
0750: protected ImageIcon getIcon() {
0751: if (icon == null)
0752: icon = new ImageIcon(org.openide.util.Utilities
0753: .loadImage(CLASS));
0754: return icon;
0755: }
0756:
0757: protected String getLeftHtmlText() {
0758: if (leftText == null) {
0759: StringBuilder sb = new StringBuilder();
0760: sb.append(getColor());
0761: if (isDeprecated)
0762: sb.append(STRIKE);
0763: sb.append(escape(typeName));
0764: for (int i = 0; i < dim; i++)
0765: sb.append("[]"); //NOI18N
0766: if (isDeprecated)
0767: sb.append(STRIKE_END);
0768: if (enclName != null && enclName.length() > 0) {
0769: sb.append(COLOR_END);
0770: sb.append(PKG_COLOR);
0771: sb.append(" ("); //NOI18N
0772: sb.append(enclName);
0773: sb.append(")"); //NOI18N
0774: }
0775: sb.append(COLOR_END);
0776: leftText = sb.toString();
0777: }
0778: return leftText;
0779: }
0780:
0781: protected String getColor() {
0782: return CLASS_COLOR;
0783: }
0784:
0785: protected void substituteText(final JTextComponent c,
0786: final int offset, int len, String toAdd) {
0787: final BaseDocument doc = (BaseDocument) c.getDocument();
0788: final StringBuilder text = new StringBuilder();
0789: final int semiPos = toAdd != null && toAdd.endsWith(";") ? findPositionForSemicolon(c)
0790: : -2; //NOI18N
0791: if (semiPos > -2)
0792: toAdd = toAdd.length() > 1 ? toAdd.substring(0, toAdd
0793: .length() - 1) : null;
0794: if (toAdd != null && !toAdd.equals("\n")) {//NOI18N
0795: TokenSequence<JavaTokenId> sequence = SourceUtils
0796: .getJavaTokenSequence(TokenHierarchy.get(doc),
0797: offset + len);
0798: if (sequence == null || !sequence.moveNext()
0799: && !sequence.movePrevious()) {
0800: text.append(toAdd);
0801: toAdd = null;
0802: }
0803: boolean added = false;
0804: while (toAdd != null && toAdd.length() > 0) {
0805: String tokenText = sequence.token().text()
0806: .toString();
0807: if (tokenText.startsWith(toAdd)) {
0808: len = sequence.offset() - offset
0809: + toAdd.length();
0810: text.append(toAdd);
0811: toAdd = null;
0812: } else if (toAdd.startsWith(tokenText)) {
0813: sequence.moveNext();
0814: len = sequence.offset() - offset;
0815: text.append(toAdd.substring(0, tokenText
0816: .length()));
0817: toAdd = toAdd.substring(tokenText.length());
0818: added = true;
0819: } else if (sequence.token().id() == JavaTokenId.WHITESPACE
0820: && sequence.token().text().toString()
0821: .indexOf('\n') < 0) {//NOI18N
0822: if (!sequence.moveNext()) {
0823: text.append(toAdd);
0824: toAdd = null;
0825: }
0826: } else {
0827: if (!added)
0828: text.append(toAdd);
0829: toAdd = null;
0830: }
0831: }
0832: }
0833: final int finalLen = len;
0834: JavaSource js = JavaSource.forDocument(doc);
0835: try {
0836: js.runUserActionTask(new Task<CompilationController>() {
0837:
0838: public void run(CompilationController controller)
0839: throws IOException {
0840: controller.toPhase(Phase.RESOLVED);
0841: DeclaredType type = typeHandle
0842: .resolve(controller);
0843: TypeElement elem = (TypeElement) type
0844: .asElement();
0845: boolean asTemplate = false;
0846: StringBuilder sb = new StringBuilder();
0847: int cnt = 1;
0848: sb.append("${PAR"); //NOI18N
0849: sb.append(cnt++);
0850: if ((type == null || type.getKind() != TypeKind.ERROR)
0851: && EnumSet
0852: .range(ElementKind.PACKAGE,
0853: ElementKind.INTERFACE)
0854: .contains(
0855: elem
0856: .getEnclosingElement()
0857: .getKind())) {
0858: sb.append(" type=\""); //NOI18N
0859: sb.append(elem.getQualifiedName());
0860: sb.append("\" default=\""); //NOI18N
0861: sb.append(elem.getSimpleName());
0862: } else {
0863: sb.append(" default=\""); //NOI18N
0864: sb.append(elem.getQualifiedName());
0865: }
0866: sb.append("\" editable=false}"); //NOI18N
0867: Iterator<? extends TypeMirror> tas = type != null ? type
0868: .getTypeArguments().iterator()
0869: : null;
0870: if (tas != null && tas.hasNext()) {
0871: sb.append('<'); //NOI18N
0872: while (tas.hasNext()) {
0873: TypeMirror ta = tas.next();
0874: sb.append("${PAR"); //NOI18N
0875: sb.append(cnt++);
0876: if (ta.getKind() == TypeKind.TYPEVAR) {
0877: TypeVariable tv = (TypeVariable) ta;
0878: if (elem == tv.asElement()
0879: .getEnclosingElement()) {
0880: sb.append(" type=\""); //NOI18N
0881: ta = tv.getUpperBound();
0882: sb.append(Utilities
0883: .getTypeName(ta, true));
0884: sb.append("\" default=\""); //NOI18N
0885: sb
0886: .append(Utilities
0887: .getTypeName(
0888: ta,
0889: false));
0890: } else {
0891: sb
0892: .append(" editable=false default=\""); //NOI18N
0893: sb.append(Utilities
0894: .getTypeName(ta, true));
0895: asTemplate = true;
0896: }
0897: sb.append("\"}"); //NOI18N
0898: } else if (ta.getKind() == TypeKind.WILDCARD) {
0899: sb.append(" type=\""); //NOI18N
0900: TypeMirror bound = ((WildcardType) ta)
0901: .getExtendsBound();
0902: if (bound == null)
0903: bound = ((WildcardType) ta)
0904: .getSuperBound();
0905: sb.append(bound != null ? Utilities
0906: .getTypeName(bound, true)
0907: : "Object"); //NOI18N
0908: sb.append("\" default=\""); //NOI18N
0909: sb.append(bound != null ? Utilities
0910: .getTypeName(bound, false)
0911: : "Object"); //NOI18N
0912: sb.append("\"}"); //NOI18N
0913: asTemplate = true;
0914: } else if (ta.getKind() == TypeKind.ERROR) {
0915: sb.append(" default=\""); //NOI18N
0916: sb.append(((ErrorType) ta)
0917: .asElement()
0918: .getSimpleName());
0919: sb.append("\"}"); //NOI18N
0920: asTemplate = true;
0921: } else {
0922: sb.append(" type=\""); //NOI18N
0923: sb.append(Utilities.getTypeName(ta,
0924: true));
0925: sb.append("\" default=\""); //NOI18N
0926: sb.append(Utilities.getTypeName(ta,
0927: false));
0928: sb.append("\" editable=false}"); //NOI18N
0929: asTemplate = true;
0930: }
0931: if (tas.hasNext())
0932: sb.append(", "); //NOI18N
0933: }
0934: sb.append('>'); //NOI18N
0935: }
0936: for (int i = 0; i < dim; i++) {
0937: sb.append("[${PAR"); //NOI18N
0938: sb.append(cnt++);
0939: sb
0940: .append(" instanceof=\"int\" default=\"\"}]"); //NOI18N
0941: asTemplate = true;
0942: }
0943: if (asTemplate) {
0944: if (insideNew)
0945: sb.append("${cursor completionInvoke}"); //NOI18N
0946: if (finalLen > 0) {
0947: doc.atomicLock();
0948: try {
0949: doc.remove(offset, finalLen);
0950: } catch (BadLocationException e) {
0951: // Can't update
0952: } finally {
0953: doc.atomicUnlock();
0954: }
0955: }
0956: CodeTemplateManager ctm = CodeTemplateManager
0957: .get(doc);
0958: if (ctm != null)
0959: ctm.createTemporary(
0960: sb.append(text).toString())
0961: .insert(c);
0962: } else {
0963: // Update the text
0964: doc.atomicLock();
0965: try {
0966: Position semiPosition = semiPos > -1
0967: && !insideNew ? doc
0968: .createPosition(semiPos) : null;
0969: TreePath tp = controller
0970: .getTreeUtilities().pathFor(
0971: offset);
0972: CharSequence cs = enclName == null ? elem
0973: .getSimpleName()
0974: : AutoImport
0975: .resolveImport(
0976: controller,
0977: tp,
0978: controller
0979: .getTypes()
0980: .getDeclaredType(
0981: elem));
0982: if (!insideNew)
0983: cs = text.insert(0, cs);
0984: String textToReplace = doc.getText(
0985: offset, finalLen);
0986: if (textToReplace.contentEquals(cs))
0987: return;
0988: doc.remove(offset, finalLen);
0989: doc.insertString(offset, cs.toString(),
0990: null);
0991: if (semiPosition != null)
0992: doc.insertString(semiPosition
0993: .getOffset(), ";", null); //NOI18N
0994: } catch (BadLocationException e) {
0995: // Can't update
0996: } finally {
0997: doc.atomicUnlock();
0998: }
0999: if (insideNew
1000: && type != null
1001: && type.getKind() == TypeKind.DECLARED) {
1002: ExecutableElement ctor = null;
1003: Trees trees = controller.getTrees();
1004: Scope scope = controller
1005: .getTreeUtilities().scopeFor(
1006: offset);
1007: int val = 0; // no constructors seen yet
1008: for (ExecutableElement ee : ElementFilter
1009: .constructorsIn(elem
1010: .getEnclosedElements())) {
1011: if (trees.isAccessible(scope, ee,
1012: type)) {
1013: if (ctor != null) {
1014: val = 2; // more than one accessible constructors seen
1015: break;
1016: }
1017: ctor = ee;
1018: }
1019: val = 1; // constructor seen
1020: }
1021: if (val != 1 || ctor != null) {
1022: final JavaCompletionItem item = val == 0 ? createDefaultConstructorItem(
1023: elem, offset, true)
1024: : val == 2
1025: || Utilities
1026: .hasAccessibleInnerClassConstructor(
1027: elem,
1028: scope,
1029: trees) ? null
1030: : createExecutableItem(
1031: ctor,
1032: (ExecutableType) controller
1033: .getTypes()
1034: .asMemberOf(
1035: type,
1036: ctor),
1037: offset,
1038: false,
1039: false,
1040: false, true);
1041: try {
1042: final Position offPosition = doc
1043: .createPosition(offset);
1044: SwingUtilities
1045: .invokeLater(new Runnable() {
1046: public void run() {
1047: if (item != null) {
1048: item
1049: .substituteText(
1050: c,
1051: offPosition
1052: .getOffset(),
1053: c
1054: .getSelectionEnd()
1055: - offPosition
1056: .getOffset(),
1057: text
1058: .toString());
1059: } else {
1060: //Temporary ugly solution
1061: SwingUtilities
1062: .invokeLater(new Runnable() {
1063: public void run() {
1064: Completion
1065: .get()
1066: .showCompletion();
1067: }
1068: });
1069: }
1070: }
1071: });
1072: } catch (BadLocationException e) {
1073: }
1074: }
1075: }
1076: }
1077: }
1078: }, true);
1079: } catch (IOException ioe) {
1080: }
1081: }
1082:
1083: public String toString() {
1084: return simpleName;
1085: }
1086: }
1087:
1088: static class InterfaceItem extends ClassItem {
1089:
1090: private static final String INTERFACE = "org/netbeans/modules/editor/resources/completion/interface.png"; // NOI18N
1091: private static final String INTERFACE_COLOR = "<font color=#404040>"; //NOI18N
1092: private static ImageIcon icon;
1093:
1094: private InterfaceItem(TypeElement elem, DeclaredType type,
1095: int dim, int substitutionOffset,
1096: boolean displayPkgName, boolean isDeprecated,
1097: boolean insideNew, boolean smartType) {
1098: super (elem, type, dim, substitutionOffset, displayPkgName,
1099: isDeprecated, insideNew, smartType);
1100: }
1101:
1102: protected ImageIcon getIcon() {
1103: if (icon == null)
1104: icon = new ImageIcon(org.openide.util.Utilities
1105: .loadImage(INTERFACE));
1106: return icon;
1107: }
1108:
1109: protected String getColor() {
1110: return INTERFACE_COLOR;
1111: }
1112: }
1113:
1114: static class EnumItem extends ClassItem {
1115:
1116: private static final String ENUM = "org/netbeans/modules/editor/resources/completion/enum.png"; // NOI18N
1117: private static ImageIcon icon;
1118:
1119: private EnumItem(TypeElement elem, DeclaredType type, int dim,
1120: int substitutionOffset, boolean displayPkgName,
1121: boolean isDeprecated, boolean insideNew,
1122: boolean smartType) {
1123: super (elem, type, dim, substitutionOffset, displayPkgName,
1124: isDeprecated, insideNew, smartType);
1125: }
1126:
1127: protected ImageIcon getIcon() {
1128: if (icon == null)
1129: icon = new ImageIcon(org.openide.util.Utilities
1130: .loadImage(ENUM));
1131: return icon;
1132: }
1133: }
1134:
1135: static class AnnotationTypeItem extends ClassItem {
1136:
1137: private static final String ANNOTATION = "org/netbeans/modules/editor/resources/completion/annotation_type.png"; // NOI18N
1138: private static ImageIcon icon;
1139:
1140: private AnnotationTypeItem(TypeElement elem, DeclaredType type,
1141: int dim, int substitutionOffset,
1142: boolean displayPkgName, boolean isDeprecated,
1143: boolean insideNew, boolean smartType) {
1144: super (elem, type, dim, substitutionOffset, displayPkgName,
1145: isDeprecated, insideNew, smartType);
1146: }
1147:
1148: protected ImageIcon getIcon() {
1149: if (icon == null)
1150: icon = new ImageIcon(org.openide.util.Utilities
1151: .loadImage(ANNOTATION));
1152: return icon;
1153: }
1154: }
1155:
1156: static class TypeParameterItem extends JavaCompletionItem {
1157:
1158: private static final String TYPE_PARAMETER_COLOR = "<font color=#000000>"; //NOI18N
1159:
1160: private String simpleName;
1161: private String leftText;
1162:
1163: private TypeParameterItem(TypeParameterElement elem,
1164: int substitutionOffset) {
1165: super (substitutionOffset);
1166: this .simpleName = elem.getSimpleName().toString();
1167: }
1168:
1169: public int getSortPriority() {
1170: return 700;
1171: }
1172:
1173: public CharSequence getSortText() {
1174: return simpleName;
1175: }
1176:
1177: public CharSequence getInsertPrefix() {
1178: return simpleName;
1179: }
1180:
1181: protected String getLeftHtmlText() {
1182: if (leftText == null)
1183: leftText = TYPE_PARAMETER_COLOR + simpleName
1184: + COLOR_END;
1185: return leftText;
1186: }
1187:
1188: public String toString() {
1189: return simpleName;
1190: }
1191: }
1192:
1193: static class VariableItem extends JavaCompletionItem {
1194:
1195: private static final String LOCAL_VARIABLE = "org/netbeans/modules/editor/resources/completion/localVariable.gif"; //NOI18N
1196: private static final String PARAMETER_COLOR = "<font color=#00007c>"; //NOI18N
1197: private static ImageIcon icon;
1198:
1199: private String varName;
1200: private boolean smartType;
1201: private String typeName;
1202: private String leftText;
1203: private String rightText;
1204:
1205: private VariableItem(TypeMirror type, String varName,
1206: int substitutionOffset, boolean smartType) {
1207: super (substitutionOffset);
1208: this .varName = varName;
1209: this .smartType = smartType;
1210: this .typeName = type != null ? Utilities.getTypeName(type,
1211: false).toString() : null;
1212: }
1213:
1214: public int getSortPriority() {
1215: return smartType ? 200 - SMART_TYPE : 200;
1216: }
1217:
1218: public CharSequence getSortText() {
1219: return varName;
1220: }
1221:
1222: public CharSequence getInsertPrefix() {
1223: return varName;
1224: }
1225:
1226: protected String getLeftHtmlText() {
1227: if (leftText == null)
1228: leftText = PARAMETER_COLOR + BOLD + varName + BOLD_END
1229: + COLOR_END;
1230: return leftText;
1231: }
1232:
1233: protected String getRightHtmlText() {
1234: if (rightText == null)
1235: rightText = escape(typeName);
1236: return rightText;
1237: }
1238:
1239: protected ImageIcon getIcon() {
1240: if (icon == null)
1241: icon = new ImageIcon(org.openide.util.Utilities
1242: .loadImage(LOCAL_VARIABLE));
1243: return icon;
1244: }
1245:
1246: public String toString() {
1247: return (typeName != null ? typeName + " " : "") + varName; //NOI18N
1248: }
1249: }
1250:
1251: static class FieldItem extends JavaCompletionItem {
1252:
1253: private static final String FIELD_PUBLIC = "org/netbeans/modules/editor/resources/completion/field_16.png"; //NOI18N
1254: private static final String FIELD_PROTECTED = "org/netbeans/modules/editor/resources/completion/field_protected_16.png"; //NOI18N
1255: private static final String FIELD_PACKAGE = "org/netbeans/modules/editor/resources/completion/field_package_private_16.png"; //NOI18N
1256: private static final String FIELD_PRIVATE = "org/netbeans/modules/editor/resources/completion/field_private_16.png"; //NOI18N
1257: private static final String FIELD_ST_PUBLIC = "org/netbeans/modules/editor/resources/completion/field_static_16.png"; //NOI18N
1258: private static final String FIELD_ST_PROTECTED = "org/netbeans/modules/editor/resources/completion/field_static_protected_16.png"; //NOI18N
1259: private static final String FIELD_ST_PACKAGE = "org/netbeans/modules/editor/resources/completion/field_static_package_private_16.png"; //NOI18N
1260: private static final String FIELD_ST_PRIVATE = "org/netbeans/modules/editor/resources/completion/field_static_private_16.png"; //NOI18N
1261: private static final String FIELD_COLOR = "<font color=#008618>"; //NOI18N
1262: private static ImageIcon icon[][] = new ImageIcon[2][4];
1263:
1264: private ElementHandle<VariableElement> elementHandle;
1265: private boolean isInherited;
1266: private boolean isDeprecated;
1267: private boolean smartType;
1268: private String simpleName;
1269: private Set<Modifier> modifiers;
1270: private String typeName;
1271: private String leftText;
1272: private String rightText;
1273:
1274: private FieldItem(VariableElement elem, TypeMirror type,
1275: int substitutionOffset, boolean isInherited,
1276: boolean isDeprecated, boolean smartType) {
1277: super (substitutionOffset);
1278: this .elementHandle = ElementHandle.create(elem);
1279: this .isInherited = isInherited;
1280: this .isDeprecated = isDeprecated;
1281: this .smartType = smartType;
1282: this .simpleName = elem.getSimpleName().toString();
1283: this .modifiers = elem.getModifiers();
1284: this .typeName = Utilities.getTypeName(type, false)
1285: .toString();
1286: }
1287:
1288: public int getSortPriority() {
1289: return smartType ? 300 - SMART_TYPE : 300;
1290: }
1291:
1292: public CharSequence getSortText() {
1293: return simpleName;
1294: }
1295:
1296: public CharSequence getInsertPrefix() {
1297: return simpleName;
1298: }
1299:
1300: public CompletionTask createDocumentationTask() {
1301: return JavaCompletionProvider.createDocTask(elementHandle);
1302: }
1303:
1304: protected String getLeftHtmlText() {
1305: if (leftText == null) {
1306: StringBuilder sb = new StringBuilder();
1307: sb.append(FIELD_COLOR);
1308: if (!isInherited)
1309: sb.append(BOLD);
1310: if (isDeprecated)
1311: sb.append(STRIKE);
1312: sb.append(simpleName);
1313: if (isDeprecated)
1314: sb.append(STRIKE_END);
1315: if (!isInherited)
1316: sb.append(BOLD_END);
1317: sb.append(COLOR_END);
1318: leftText = sb.toString();
1319: }
1320: return leftText;
1321: }
1322:
1323: protected String getRightHtmlText() {
1324: if (rightText == null)
1325: rightText = escape(typeName);
1326: return rightText;
1327: }
1328:
1329: protected ImageIcon getIcon() {
1330: int level = getProtectionLevel(modifiers);
1331: boolean isStatic = modifiers.contains(Modifier.STATIC);
1332: ImageIcon cachedIcon = icon[isStatic ? 1 : 0][level];
1333: if (cachedIcon != null)
1334: return cachedIcon;
1335:
1336: String iconPath = FIELD_PUBLIC;
1337: if (isStatic) {
1338: switch (level) {
1339: case PRIVATE_LEVEL:
1340: iconPath = FIELD_ST_PRIVATE;
1341: break;
1342:
1343: case PACKAGE_LEVEL:
1344: iconPath = FIELD_ST_PACKAGE;
1345: break;
1346:
1347: case PROTECTED_LEVEL:
1348: iconPath = FIELD_ST_PROTECTED;
1349: break;
1350:
1351: case PUBLIC_LEVEL:
1352: iconPath = FIELD_ST_PUBLIC;
1353: break;
1354: }
1355: } else {
1356: switch (level) {
1357: case PRIVATE_LEVEL:
1358: iconPath = FIELD_PRIVATE;
1359: break;
1360:
1361: case PACKAGE_LEVEL:
1362: iconPath = FIELD_PACKAGE;
1363: break;
1364:
1365: case PROTECTED_LEVEL:
1366: iconPath = FIELD_PROTECTED;
1367: break;
1368:
1369: case PUBLIC_LEVEL:
1370: iconPath = FIELD_PUBLIC;
1371: break;
1372: }
1373: }
1374: ImageIcon newIcon = new ImageIcon(
1375: org.openide.util.Utilities.loadImage(iconPath));
1376: icon[isStatic ? 1 : 0][level] = newIcon;
1377: return newIcon;
1378: }
1379:
1380: public String toString() {
1381: StringBuilder sb = new StringBuilder();
1382: for (Modifier mod : modifiers) {
1383: sb.append(mod.toString());
1384: sb.append(' ');
1385: }
1386: sb.append(typeName);
1387: sb.append(' ');
1388: sb.append(simpleName);
1389: return sb.toString();
1390: }
1391: }
1392:
1393: static class MethodItem extends JavaCompletionItem {
1394:
1395: private static final String METHOD_PUBLIC = "org/netbeans/modules/editor/resources/completion/method_16.png"; //NOI18N
1396: private static final String METHOD_PROTECTED = "org/netbeans/modules/editor/resources/completion/method_protected_16.png"; //NOI18N
1397: private static final String METHOD_PACKAGE = "org/netbeans/modules/editor/resources/completion/method_package_private_16.png"; //NOI18N
1398: private static final String METHOD_PRIVATE = "org/netbeans/modules/editor/resources/completion/method_private_16.png"; //NOI18N
1399: private static final String METHOD_ST_PUBLIC = "org/netbeans/modules/editor/resources/completion/method_static_16.png"; //NOI18N
1400: private static final String METHOD_ST_PROTECTED = "org/netbeans/modules/editor/resources/completion/method_static_protected_16.png"; //NOI18N
1401: private static final String METHOD_ST_PRIVATE = "org/netbeans/modules/editor/resources/completion/method_static_private_16.png"; //NOI18N
1402: private static final String METHOD_ST_PACKAGE = "org/netbeans/modules/editor/resources/completion/method_static_package_private_16.png"; //NOI18N
1403: private static final String METHOD_COLOR = "<font color=#000000>"; //NOI18N
1404: private static final String PARAMETER_NAME_COLOR = "<font color=#a06001>"; //NOI18N
1405: private static ImageIcon icon[][] = new ImageIcon[2][4];
1406:
1407: protected ElementHandle<ExecutableElement> elementHandle;
1408: private boolean isInherited;
1409: private boolean isDeprecated;
1410: private boolean inImport;
1411: private boolean smartType;
1412: private String simpleName;
1413: protected Set<Modifier> modifiers;
1414: private List<ParamDesc> params;
1415: private String typeName;
1416: private boolean isPrimitive;
1417: private String sortText;
1418: private String leftText;
1419: private String rightText;
1420:
1421: private MethodItem(ExecutableElement elem, ExecutableType type,
1422: int substitutionOffset, boolean isInherited,
1423: boolean isDeprecated, boolean inImport,
1424: boolean smartType) {
1425: super (substitutionOffset);
1426: this .elementHandle = ElementHandle.create(elem);
1427: this .isInherited = isInherited;
1428: this .isDeprecated = isDeprecated;
1429: this .inImport = inImport;
1430: this .smartType = smartType;
1431: this .simpleName = elem.getSimpleName().toString();
1432: this .modifiers = elem.getModifiers();
1433: this .params = new ArrayList<ParamDesc>();
1434: Iterator<? extends VariableElement> it = elem
1435: .getParameters().iterator();
1436: Iterator<? extends TypeMirror> tIt = type
1437: .getParameterTypes().iterator();
1438: while (it.hasNext() && tIt.hasNext()) {
1439: TypeMirror tm = tIt.next();
1440: this .params.add(new ParamDesc(tm.toString(), Utilities
1441: .getTypeName(tm, false,
1442: elem.isVarArgs() && !tIt.hasNext())
1443: .toString(), it.next().getSimpleName()
1444: .toString()));
1445: }
1446: TypeMirror retType = type.getReturnType();
1447: this .typeName = Utilities.getTypeName(retType, false)
1448: .toString();
1449: this .isPrimitive = retType.getKind().isPrimitive()
1450: || retType.getKind() == TypeKind.VOID;
1451: }
1452:
1453: public int getSortPriority() {
1454: return smartType ? 500 - SMART_TYPE : 500;
1455: }
1456:
1457: public CharSequence getSortText() {
1458: if (sortText == null) {
1459: StringBuilder sortParams = new StringBuilder();
1460: sortParams.append('(');
1461: int cnt = 0;
1462: for (Iterator<ParamDesc> it = params.iterator(); it
1463: .hasNext();) {
1464: ParamDesc param = it.next();
1465: sortParams.append(param.typeName);
1466: if (it.hasNext()) {
1467: sortParams.append(',');
1468: }
1469: cnt++;
1470: }
1471: sortParams.append(')');
1472: sortText = simpleName + "#"
1473: + ((cnt < 10 ? "0" : "") + cnt) + "#"
1474: + sortParams.toString(); //NOI18N
1475: }
1476: return sortText;
1477: }
1478:
1479: public CharSequence getInsertPrefix() {
1480: return simpleName;
1481: }
1482:
1483: protected String getLeftHtmlText() {
1484: if (leftText == null) {
1485: StringBuilder lText = new StringBuilder();
1486: lText.append(METHOD_COLOR);
1487: if (!isInherited)
1488: lText.append(BOLD);
1489: if (isDeprecated)
1490: lText.append(STRIKE);
1491: lText.append(simpleName);
1492: if (isDeprecated)
1493: lText.append(STRIKE_END);
1494: if (!isInherited)
1495: lText.append(BOLD_END);
1496: lText.append(COLOR_END);
1497: lText.append('(');
1498: for (Iterator<ParamDesc> it = params.iterator(); it
1499: .hasNext();) {
1500: ParamDesc paramDesc = it.next();
1501: lText.append(escape(paramDesc.typeName));
1502: lText.append(' ');
1503: lText.append(PARAMETER_NAME_COLOR);
1504: lText.append(paramDesc.name);
1505: lText.append(COLOR_END);
1506: if (it.hasNext()) {
1507: lText.append(", "); //NOI18N
1508: }
1509: }
1510: lText.append(')');
1511: return lText.toString();
1512: }
1513: return leftText;
1514: }
1515:
1516: protected String getRightHtmlText() {
1517: if (rightText == null)
1518: rightText = escape(typeName);
1519: return rightText;
1520: }
1521:
1522: public CompletionTask createDocumentationTask() {
1523: return JavaCompletionProvider.createDocTask(elementHandle);
1524: }
1525:
1526: protected ImageIcon getIcon() {
1527: int level = getProtectionLevel(modifiers);
1528: boolean isStatic = modifiers.contains(Modifier.STATIC);
1529: ImageIcon cachedIcon = icon[isStatic ? 1 : 0][level];
1530: if (cachedIcon != null)
1531: return cachedIcon;
1532:
1533: String iconPath = METHOD_PUBLIC;
1534: if (isStatic) {
1535: switch (level) {
1536: case PRIVATE_LEVEL:
1537: iconPath = METHOD_ST_PRIVATE;
1538: break;
1539:
1540: case PACKAGE_LEVEL:
1541: iconPath = METHOD_ST_PACKAGE;
1542: break;
1543:
1544: case PROTECTED_LEVEL:
1545: iconPath = METHOD_ST_PROTECTED;
1546: break;
1547:
1548: case PUBLIC_LEVEL:
1549: iconPath = METHOD_ST_PUBLIC;
1550: break;
1551: }
1552: } else {
1553: switch (level) {
1554: case PRIVATE_LEVEL:
1555: iconPath = METHOD_PRIVATE;
1556: break;
1557:
1558: case PACKAGE_LEVEL:
1559: iconPath = METHOD_PACKAGE;
1560: break;
1561:
1562: case PROTECTED_LEVEL:
1563: iconPath = METHOD_PROTECTED;
1564: break;
1565:
1566: case PUBLIC_LEVEL:
1567: iconPath = METHOD_PUBLIC;
1568: break;
1569: }
1570: }
1571: ImageIcon newIcon = new ImageIcon(
1572: org.openide.util.Utilities.loadImage(iconPath));
1573: icon[isStatic ? 1 : 0][level] = newIcon;
1574: return newIcon;
1575: }
1576:
1577: protected void substituteText(final JTextComponent c,
1578: int offset, int len, String toAdd) {
1579: if (toAdd == null) {
1580: if (isPrimitive) {
1581: try {
1582: final String[] ret = new String[1];
1583: JavaSource js = JavaSource.forDocument(c
1584: .getDocument());
1585: js.runUserActionTask(
1586: new Task<CompilationController>() {
1587:
1588: public void run(
1589: CompilationController controller)
1590: throws Exception {
1591: controller
1592: .toPhase(JavaSource.Phase.PARSED);
1593: TreePath tp = controller
1594: .getTreeUtilities()
1595: .pathFor(
1596: c
1597: .getSelectionEnd());
1598: Tree tree = tp.getLeaf();
1599: if (tree.getKind() == Tree.Kind.IDENTIFIER
1600: || tree.getKind() == Tree.Kind.PRIMITIVE_TYPE)
1601: tp = tp.getParentPath();
1602: if (tp.getLeaf().getKind() == Tree.Kind.MEMBER_SELECT
1603: || (tp.getLeaf()
1604: .getKind() == Tree.Kind.METHOD_INVOCATION && ((MethodInvocationTree) tp
1605: .getLeaf())
1606: .getMethodSelect() == tree))
1607: tp = tp.getParentPath();
1608: if (tp.getLeaf().getKind() == Tree.Kind.EXPRESSION_STATEMENT
1609: || tp.getLeaf()
1610: .getKind() == Tree.Kind.BLOCK)
1611: ret[0] = ";"; //NOI18N
1612: }
1613: }, true);
1614: toAdd = ret[0];
1615: } catch (IOException ex) {
1616: }
1617: }
1618: }
1619: if (inImport || params.isEmpty()) {
1620: String add = inImport ? ";"
1621: : CodeStyle.getDefault(null)
1622: .spaceBeforeMethodCallParen() ? " ()"
1623: : "()"; //NOI18N
1624: if (toAdd != null && !add.startsWith(toAdd))
1625: add += toAdd;
1626: super .substituteText(c, offset, len, add);
1627: } else {
1628: String add = "()"; //NOI18N
1629: if (toAdd != null && !add.startsWith(toAdd))
1630: add += toAdd;
1631: BaseDocument doc = (BaseDocument) c.getDocument();
1632: String text = ""; //NOI18N
1633: int semiPos = add.endsWith(";") ? findPositionForSemicolon(c)
1634: : -2; //NOI18N
1635: if (semiPos > -2)
1636: add = add.length() > 1 ? add.substring(0, add
1637: .length() - 1) : null;
1638: TokenSequence<JavaTokenId> sequence = SourceUtils
1639: .getJavaTokenSequence(TokenHierarchy.get(doc),
1640: offset + len);
1641: if (sequence == null || !sequence.moveNext()
1642: && !sequence.movePrevious()) {
1643: text += add;
1644: add = null;
1645: }
1646: boolean added = false;
1647: while (add != null && add.length() > 0) {
1648: String tokenText = sequence.token().text()
1649: .toString();
1650: if (tokenText.startsWith(add)) {
1651: len = sequence.offset() - offset + add.length();
1652: text += add;
1653: add = null;
1654: } else if (add.startsWith(tokenText)) {
1655: sequence.moveNext();
1656: len = sequence.offset() - offset;
1657: text += add.substring(0, tokenText.length());
1658: add = add.substring(tokenText.length());
1659: added = true;
1660: } else if (sequence.token().id() == JavaTokenId.WHITESPACE
1661: && sequence.token().text().toString()
1662: .indexOf('\n') < 0) {//NOI18N
1663: if (!sequence.moveNext()) {
1664: text += add;
1665: add = null;
1666: }
1667: } else {
1668: if (!added)
1669: text += add;
1670: add = null;
1671: }
1672: }
1673: doc.atomicLock();
1674: try {
1675: Position semiPosition = semiPos > -1 ? doc
1676: .createPosition(semiPos) : null;
1677: if (len > 0)
1678: doc.remove(offset, len);
1679: if (semiPosition != null)
1680: doc.insertString(semiPosition.getOffset(), ";",
1681: null); //NOI18N
1682: else if (params.isEmpty() && "(".equals(toAdd)) //NOI18N
1683: c.setCaretPosition(c.getCaretPosition() - 1);
1684: } catch (BadLocationException e) {
1685: // Can't update
1686: } finally {
1687: doc.atomicUnlock();
1688: }
1689: CodeTemplateManager ctm = CodeTemplateManager.get(doc);
1690: if (ctm != null) {
1691: StringBuilder sb = new StringBuilder();
1692: sb.append(getInsertPrefix());
1693: if (CodeStyle.getDefault(null)
1694: .spaceBeforeMethodCallParen())
1695: sb.append(' '); //NOI18N
1696: sb.append('('); //NOI18N
1697: if (text.length() > 1) {
1698: for (Iterator<ParamDesc> it = params.iterator(); it
1699: .hasNext();) {
1700: ParamDesc paramDesc = it.next();
1701: sb.append("${"); //NOI18N
1702: sb.append(paramDesc.name);
1703: sb.append(" named instanceof="); //NOI18N
1704: sb.append(paramDesc.fullTypeName);
1705: sb.append('}'); //NOI18N
1706: if (it.hasNext())
1707: sb.append(", "); //NOI18N
1708: }
1709: sb.append(')');//NOI18N
1710: if (text.length() > 2)
1711: sb.append(text.substring(2));
1712: }
1713: ctm.createTemporary(sb.toString()).insert(c);
1714: Completion.get().showToolTip();
1715: }
1716: }
1717: }
1718:
1719: public String toString() {
1720: StringBuilder sb = new StringBuilder();
1721: for (Modifier mod : modifiers) {
1722: sb.append(mod.toString());
1723: sb.append(' ');
1724: }
1725: sb.append(typeName);
1726: sb.append(' ');
1727: sb.append(simpleName);
1728: sb.append('(');
1729: for (Iterator<ParamDesc> it = params.iterator(); it
1730: .hasNext();) {
1731: ParamDesc paramDesc = it.next();
1732: sb.append(paramDesc.typeName);
1733: sb.append(' ');
1734: sb.append(paramDesc.name);
1735: if (it.hasNext()) {
1736: sb.append(", "); //NOI18N
1737: }
1738: }
1739: sb.append(')');
1740: return sb.toString();
1741: }
1742: }
1743:
1744: static class OverrideMethodItem extends MethodItem {
1745:
1746: private static final String IMPL_BADGE_PATH = "org/netbeans/modules/java/editor/resources/implement_badge.png";
1747: private static final String OVRD_BADGE_PATH = "org/netbeans/modules/java/editor/resources/override_badge.png";
1748:
1749: private static final String OVERRIDE_TEXT = NbBundle
1750: .getMessage(JavaCompletionItem.class, "override_Lbl");
1751: private static final String IMPLEMENT_TEXT = NbBundle
1752: .getMessage(JavaCompletionItem.class, "implement_Lbl");
1753:
1754: private static ImageIcon implementBadge = new ImageIcon(
1755: org.openide.util.Utilities.loadImage(IMPL_BADGE_PATH));
1756: private static ImageIcon overrideBadge = new ImageIcon(
1757: org.openide.util.Utilities.loadImage(OVRD_BADGE_PATH));
1758: private static ImageIcon merged_icon[][] = new ImageIcon[2][4];
1759:
1760: private boolean implement;
1761: private String leftText;
1762:
1763: private OverrideMethodItem(ExecutableElement elem,
1764: ExecutableType type, int substitutionOffset,
1765: boolean implement) {
1766: super (elem, type, substitutionOffset, false, false, false,
1767: false);
1768: this .implement = implement;
1769: }
1770:
1771: protected String getLeftHtmlText() {
1772: if (leftText == null) {
1773: leftText = super .getLeftHtmlText() + " - ";
1774: leftText += (implement ? IMPLEMENT_TEXT : OVERRIDE_TEXT);
1775: }
1776: return leftText;
1777: }
1778:
1779: @Override
1780: protected ImageIcon getIcon() {
1781: int level = getProtectionLevel(modifiers);
1782: ImageIcon merged = merged_icon[implement ? 0 : 1][level];
1783: if (merged != null) {
1784: return merged;
1785: }
1786: ImageIcon super Icon = super .getIcon();
1787: merged = new ImageIcon(org.openide.util.Utilities
1788: .mergeImages(super Icon.getImage(),
1789: implement ? implementBadge.getImage()
1790: : overrideBadge.getImage(), 16 - 8,
1791: 16 - 8));
1792:
1793: merged_icon[implement ? 0 : 1][level] = merged;
1794: return merged;
1795: }
1796:
1797: protected void substituteText(final JTextComponent c,
1798: final int offset, final int len, String toAdd) {
1799: BaseDocument doc = (BaseDocument) c.getDocument();
1800: if (len > 0) {
1801: doc.atomicLock();
1802: try {
1803: doc.remove(offset, len);
1804: } catch (BadLocationException e) {
1805: // Can't update
1806: } finally {
1807: doc.atomicUnlock();
1808: }
1809: }
1810: try {
1811: JavaSource js = JavaSource.forDocument(doc);
1812: js.runModificationTask(new Task<WorkingCopy>() {
1813:
1814: public void run(WorkingCopy copy)
1815: throws IOException {
1816: copy.toPhase(Phase.ELEMENTS_RESOLVED);
1817: ExecutableElement ee = elementHandle
1818: .resolve(copy);
1819: if (ee == null)
1820: return;
1821: TreePath tp = copy.getTreeUtilities().pathFor(
1822: offset);
1823: if (tp.getLeaf().getKind() == Tree.Kind.CLASS) {
1824: if (Utilities.isInMethod(tp))
1825: copy.toPhase(Phase.RESOLVED);
1826: int idx = 0;
1827: for (Tree tree : ((ClassTree) tp.getLeaf())
1828: .getMembers()) {
1829: if (copy
1830: .getTrees()
1831: .getSourcePositions()
1832: .getStartPosition(
1833: tp.getCompilationUnit(),
1834: tree) < offset)
1835: idx++;
1836: else
1837: break;
1838: }
1839: if (implement)
1840: GeneratorUtils
1841: .generateAbstractMethodImplementation(
1842: copy, tp, ee, idx);
1843: else
1844: GeneratorUtils.generateMethodOverride(
1845: copy, tp, ee, idx);
1846: }
1847: }
1848: }).commit();
1849: } catch (IOException ex) {
1850: Logger.getLogger("global").log(Level.WARNING, null, ex);
1851: }
1852: }
1853:
1854: public String toString() {
1855: StringBuilder sb = new StringBuilder();
1856: sb.append(super .toString());
1857: sb.append(" - ");
1858: sb.append(implement ? IMPLEMENT_TEXT : OVERRIDE_TEXT);
1859: return sb.toString();
1860: }
1861:
1862: public boolean instantSubstitution(JTextComponent component) {
1863: return false;//no instant substitution for override method item.
1864: }
1865: }
1866:
1867: static class GetterSetterMethodItem extends JavaCompletionItem {
1868:
1869: private static final String METHOD_PUBLIC = "org/netbeans/modules/editor/resources/completion/method_16.png"; //NOI18N
1870: private static final String GETTER_BADGE_PATH = "org/netbeans/modules/java/editor/resources/getter_badge.png"; //NOI18N
1871: private static final String SETTER_BADGE_PATH = "org/netbeans/modules/java/editor/resources/setter_badge.png"; //NOI18N
1872: private static final String METHOD_COLOR = "<font color=#000000>"; //NOI18N
1873: private static final String PARAMETER_NAME_COLOR = "<font color=#a06001>"; //NOI18N
1874:
1875: private static ImageIcon super Icon;
1876: private static ImageIcon[] merged_icons = new ImageIcon[2];
1877:
1878: protected ElementHandle<VariableElement> elementHandle;
1879: private boolean setter;
1880: private String simpleName;
1881: private String name;
1882: private String typeName;
1883: private String sortText;
1884: private String leftText;
1885: private String rightText;
1886:
1887: private GetterSetterMethodItem(VariableElement elem,
1888: TypeMirror type, int substitutionOffset, boolean setter) {
1889: super (substitutionOffset);
1890: this .elementHandle = ElementHandle.create(elem);
1891: this .setter = setter;
1892: this .simpleName = elem.getSimpleName().toString();
1893: if (setter)
1894: this .name = "set"
1895: + Character.toUpperCase(simpleName.charAt(0))
1896: + simpleName.substring(1, simpleName.length()); //NOI18N
1897: else
1898: this .name = (elem.asType().getKind() == TypeKind.BOOLEAN ? "is"
1899: : "get")
1900: + Character.toUpperCase(simpleName.charAt(0))
1901: + simpleName.substring(1, simpleName.length()); //NOI18N
1902: this .typeName = Utilities.getTypeName(type, false)
1903: .toString();
1904: }
1905:
1906: public int getSortPriority() {
1907: return 500;
1908: }
1909:
1910: public CharSequence getSortText() {
1911: if (sortText == null) {
1912: StringBuilder sortParams = new StringBuilder();
1913: sortParams.append('('); //NOI18N
1914: if (setter)
1915: sortParams.append(typeName);
1916: sortParams.append(')'); //NOI18N
1917: sortText = name + "#" + (setter ? "01" : "00") + "#"
1918: + sortParams.toString(); //NOI18N
1919: }
1920: return sortText;
1921: }
1922:
1923: public CharSequence getInsertPrefix() {
1924: return name;
1925: }
1926:
1927: @Override
1928: protected String getLeftHtmlText() {
1929: if (leftText == null) {
1930: StringBuilder lText = new StringBuilder();
1931: lText.append(METHOD_COLOR);
1932: lText.append(BOLD);
1933: lText.append(name);
1934: lText.append(BOLD_END);
1935: lText.append(COLOR_END);
1936: lText.append('(');
1937: if (setter) {
1938: lText.append(escape(typeName));
1939: lText.append(' ');
1940: lText.append(PARAMETER_NAME_COLOR);
1941: lText.append(simpleName);
1942: lText.append(COLOR_END);
1943: }
1944: lText.append(") - "); //NOI18N
1945: lText.append(GENERATE_TEXT);
1946: leftText = lText.toString();
1947: }
1948: return leftText;
1949: }
1950:
1951: @Override
1952: protected String getRightHtmlText() {
1953: if (rightText == null)
1954: rightText = setter ? "void" : escape(typeName);
1955: return rightText;
1956: }
1957:
1958: @Override
1959: protected ImageIcon getIcon() {
1960: if (merged_icons[setter ? 1 : 0] == null) {
1961: if (super Icon == null)
1962: super Icon = new ImageIcon(
1963: org.openide.util.Utilities
1964: .loadImage(METHOD_PUBLIC));
1965: if (setter) {
1966: ImageIcon setterBadge = new ImageIcon(
1967: org.openide.util.Utilities
1968: .loadImage(SETTER_BADGE_PATH));
1969: merged_icons[1] = new ImageIcon(
1970: org.openide.util.Utilities
1971: .mergeImages(super Icon.getImage(),
1972: setterBadge.getImage(),
1973: 16 - 8, 16 - 8));
1974: } else {
1975: ImageIcon getterBadge = new ImageIcon(
1976: org.openide.util.Utilities
1977: .loadImage(GETTER_BADGE_PATH));
1978: merged_icons[0] = new ImageIcon(
1979: org.openide.util.Utilities
1980: .mergeImages(super Icon.getImage(),
1981: getterBadge.getImage(),
1982: 16 - 8, 16 - 8));
1983: }
1984: }
1985: return merged_icons[setter ? 1 : 0];
1986: }
1987:
1988: @Override
1989: protected void substituteText(final JTextComponent c,
1990: final int offset, final int len, String toAdd) {
1991: BaseDocument doc = (BaseDocument) c.getDocument();
1992: if (len > 0) {
1993: doc.atomicLock();
1994: try {
1995: doc.remove(offset, len);
1996: } catch (BadLocationException e) {
1997: // Can't update
1998: } finally {
1999: doc.atomicUnlock();
2000: }
2001: }
2002: try {
2003: JavaSource js = JavaSource.forDocument(doc);
2004: js.runModificationTask(new Task<WorkingCopy>() {
2005:
2006: public void run(WorkingCopy copy)
2007: throws IOException {
2008: copy.toPhase(Phase.ELEMENTS_RESOLVED);
2009: VariableElement ve = elementHandle
2010: .resolve(copy);
2011: if (ve == null)
2012: return;
2013: TreePath tp = copy.getTreeUtilities().pathFor(
2014: offset);
2015: if (tp.getLeaf().getKind() == Tree.Kind.CLASS) {
2016: if (Utilities.isInMethod(tp))
2017: copy.toPhase(Phase.RESOLVED);
2018: int idx = 0;
2019: for (Tree tree : ((ClassTree) tp.getLeaf())
2020: .getMembers()) {
2021: if (copy
2022: .getTrees()
2023: .getSourcePositions()
2024: .getStartPosition(
2025: tp.getCompilationUnit(),
2026: tree) < offset)
2027: idx++;
2028: else
2029: break;
2030: }
2031: TypeElement te = (TypeElement) copy
2032: .getTrees().getElement(tp);
2033: if (te != null) {
2034: GeneratorUtilities gu = GeneratorUtilities
2035: .get(copy);
2036: MethodTree method = setter ? gu
2037: .createSetter(te, ve) : gu
2038: .createGetter(te, ve);
2039: ClassTree decl = copy.getTreeMaker()
2040: .insertClassMember(
2041: (ClassTree) tp
2042: .getLeaf(),
2043: idx, method);
2044: copy.rewrite(tp.getLeaf(), decl);
2045: }
2046: }
2047: }
2048: }).commit();
2049: } catch (IOException ex) {
2050: Logger.getLogger("global").log(Level.WARNING, null, ex);
2051: }
2052: }
2053:
2054: @Override
2055: public String toString() {
2056: StringBuilder sb = new StringBuilder();
2057: sb.append("public "); //NOI18N
2058: sb.append(setter ? "void" : typeName); //NOI18N
2059: sb.append(' ');
2060: sb.append(name);
2061: sb.append('(');
2062: if (setter) {
2063: sb.append(typeName);
2064: sb.append(' ');
2065: sb.append(simpleName);
2066: }
2067: sb.append(") - "); //NOI18N
2068: sb.append(GENERATE_TEXT);
2069: return sb.toString();
2070: }
2071:
2072: @Override
2073: public boolean instantSubstitution(JTextComponent component) {
2074: return false;//no instant substitution for override method item.
2075: }
2076: }
2077:
2078: static class ConstructorItem extends JavaCompletionItem {
2079:
2080: private static final String CONSTRUCTOR_PUBLIC = "org/netbeans/modules/editor/resources/completion/constructor_16.png"; //NOI18N
2081: private static final String CONSTRUCTOR_PROTECTED = "org/netbeans/modules/editor/resources/completion/constructor_protected_16.png"; //NOI18N
2082: private static final String CONSTRUCTOR_PACKAGE = "org/netbeans/modules/editor/resources/completion/constructor_package_private_16.png"; //NOI18N
2083: private static final String CONSTRUCTOR_PRIVATE = "org/netbeans/modules/editor/resources/completion/constructor_private_16.png"; //NOI18N
2084: private static final String CONSTRUCTOR_COLOR = "<font color=#b28b00>"; //NOI18N
2085: private static final String PARAMETER_NAME_COLOR = "<font color=#a06001>"; //NOI18N
2086: private static ImageIcon icon[] = new ImageIcon[4];
2087:
2088: private ElementHandle<ExecutableElement> elementHandle;
2089: private boolean isDeprecated;
2090: private boolean smartType;
2091: private String simpleName;
2092: protected Set<Modifier> modifiers;
2093: private List<ParamDesc> params;
2094: private boolean isAbstract;
2095: private String sortText;
2096: private String leftText;
2097:
2098: private ConstructorItem(ExecutableElement elem,
2099: ExecutableType type, int substitutionOffset,
2100: boolean isDeprecated, boolean smartType) {
2101: super (substitutionOffset);
2102: this .elementHandle = ElementHandle.create(elem);
2103: this .isDeprecated = isDeprecated;
2104: this .smartType = smartType;
2105: this .simpleName = elem.getEnclosingElement()
2106: .getSimpleName().toString();
2107: this .modifiers = elem.getModifiers();
2108: this .params = new ArrayList<ParamDesc>();
2109: Iterator<? extends VariableElement> it = elem
2110: .getParameters().iterator();
2111: Iterator<? extends TypeMirror> tIt = type
2112: .getParameterTypes().iterator();
2113: while (it.hasNext() && tIt.hasNext()) {
2114: TypeMirror tm = tIt.next();
2115: this .params.add(new ParamDesc(tm.toString(), Utilities
2116: .getTypeName(tm, false,
2117: elem.isVarArgs() && !tIt.hasNext())
2118: .toString(), it.next().getSimpleName()
2119: .toString()));
2120: }
2121: this .isAbstract = elem.getEnclosingElement().getModifiers()
2122: .contains(Modifier.ABSTRACT);
2123: }
2124:
2125: public int getSortPriority() {
2126: return smartType ? 650 - SMART_TYPE : 650;
2127: }
2128:
2129: public CharSequence getSortText() {
2130: if (sortText == null) {
2131: StringBuilder sortParams = new StringBuilder();
2132: sortParams.append('(');
2133: int cnt = 0;
2134: for (Iterator<ParamDesc> it = params.iterator(); it
2135: .hasNext();) {
2136: ParamDesc paramDesc = it.next();
2137: sortParams.append(paramDesc.typeName);
2138: if (it.hasNext()) {
2139: sortParams.append(',');
2140: }
2141: cnt++;
2142: }
2143: sortParams.append(')');
2144: sortText = simpleName + "#"
2145: + ((cnt < 10 ? "0" : "") + cnt) + "#"
2146: + sortParams.toString(); //NOI18N
2147: }
2148: return sortText;
2149: }
2150:
2151: public CharSequence getInsertPrefix() {
2152: return simpleName;
2153: }
2154:
2155: protected String getLeftHtmlText() {
2156: if (leftText == null) {
2157: StringBuilder lText = new StringBuilder();
2158: lText.append(CONSTRUCTOR_COLOR);
2159: lText.append(BOLD);
2160: if (isDeprecated)
2161: lText.append(STRIKE);
2162: lText.append(simpleName);
2163: if (isDeprecated)
2164: lText.append(STRIKE_END);
2165: lText.append(BOLD_END);
2166: lText.append(COLOR_END);
2167: lText.append('(');
2168: for (Iterator<ParamDesc> it = params.iterator(); it
2169: .hasNext();) {
2170: ParamDesc paramDesc = it.next();
2171: lText.append(escape(paramDesc.typeName));
2172: lText.append(' ');
2173: lText.append(PARAMETER_NAME_COLOR);
2174: lText.append(paramDesc.name);
2175: lText.append(COLOR_END);
2176: if (it.hasNext()) {
2177: lText.append(", "); //NOI18N
2178: }
2179: }
2180: lText.append(')');
2181: leftText = lText.toString();
2182: }
2183: return leftText;
2184: }
2185:
2186: public CompletionTask createDocumentationTask() {
2187: return JavaCompletionProvider.createDocTask(elementHandle);
2188: }
2189:
2190: protected ImageIcon getIcon() {
2191: int level = getProtectionLevel(modifiers);
2192: ImageIcon cachedIcon = icon[level];
2193: if (cachedIcon != null)
2194: return cachedIcon;
2195:
2196: String iconPath = CONSTRUCTOR_PUBLIC;
2197: switch (level) {
2198: case PRIVATE_LEVEL:
2199: iconPath = CONSTRUCTOR_PRIVATE;
2200: break;
2201:
2202: case PACKAGE_LEVEL:
2203: iconPath = CONSTRUCTOR_PACKAGE;
2204: break;
2205:
2206: case PROTECTED_LEVEL:
2207: iconPath = CONSTRUCTOR_PROTECTED;
2208: break;
2209:
2210: case PUBLIC_LEVEL:
2211: iconPath = CONSTRUCTOR_PUBLIC;
2212: break;
2213: }
2214: ImageIcon newIcon = new ImageIcon(
2215: org.openide.util.Utilities.loadImage(iconPath));
2216: icon[level] = newIcon;
2217: return newIcon;
2218: }
2219:
2220: protected void substituteText(JTextComponent c, int offset,
2221: int len, String toAdd) {
2222: offset += len;
2223: len = 0;
2224: int semiPos = toAdd != null && toAdd.endsWith(";") ? findPositionForSemicolon(c)
2225: : -2; //NOI18N
2226: if (semiPos > -2)
2227: toAdd = toAdd.length() > 1 ? toAdd.substring(0, toAdd
2228: .length() - 1) : null;
2229: BaseDocument doc = (BaseDocument) c.getDocument();
2230: TokenSequence<JavaTokenId> sequence = SourceUtils
2231: .getJavaTokenSequence(TokenHierarchy.get(doc),
2232: offset);
2233: if (sequence == null || !sequence.moveNext()
2234: && !sequence.movePrevious()) {
2235: sequence.movePrevious();
2236: if (sequence.token().id() == JavaTokenId.THIS
2237: || sequence.token().id() == JavaTokenId.SUPER) {
2238: isAbstract = false;
2239: if (toAdd == null)
2240: toAdd = ";"; //NOI18N
2241: }
2242: sequence.moveNext();
2243: }
2244: String add = isAbstract ? "() {}" : "()"; //NOI18N
2245: if (toAdd != null && !add.startsWith(toAdd))
2246: add += toAdd;
2247: String text = CodeStyle.getDefault(null)
2248: .spaceBeforeMethodCallParen() ? " " : ""; //NOI18N
2249: if (sequence == null) {
2250: text += add;
2251: add = null;
2252: }
2253: boolean added = false;
2254: while (add != null && add.length() > 0) {
2255: String tokenText = sequence.token().text().toString();
2256: if (tokenText.startsWith(add)) {
2257: len = sequence.offset() - offset + add.length();
2258: text += add;
2259: add = null;
2260: } else if (add.startsWith(tokenText)) {
2261: sequence.moveNext();
2262: len = sequence.offset() - offset;
2263: text += add.substring(0, tokenText.length());
2264: add = add.substring(tokenText.length());
2265: added = true;
2266: } else if (sequence.token().id() == JavaTokenId.WHITESPACE
2267: && sequence.token().text().toString().indexOf(
2268: '\n') < 0) {//NOI18N
2269: if (!sequence.moveNext()) {
2270: text += add;
2271: add = null;
2272: }
2273: } else {
2274: if (!added)
2275: text += add;
2276: add = null;
2277: }
2278: }
2279: doc.atomicLock();
2280: Position position = null;
2281: try {
2282: Position semiPosition = semiPos > -1 ? doc
2283: .createPosition(semiPos) : null;
2284: doc.remove(offset, len);
2285: doc.insertString(offset, text, null);
2286: position = doc.createPosition(offset
2287: + text.indexOf('('));
2288: if (semiPosition != null)
2289: doc.insertString(semiPosition.getOffset(), ";",
2290: null); //NOI18N
2291: else if (!isAbstract && params.isEmpty()
2292: && "(".equals(toAdd)) //NOI18N
2293: c.setCaretPosition(c.getCaretPosition() - 1);
2294: } catch (BadLocationException e) {
2295: } finally {
2296: doc.atomicUnlock();
2297: }
2298: if (isAbstract && text.length() > 3) {
2299: try {
2300: JavaSource js = JavaSource.forDocument(doc);
2301: final int off = offset + text.indexOf('{') + 1;
2302: js.runModificationTask(new Task<WorkingCopy>() {
2303:
2304: public void run(WorkingCopy copy)
2305: throws IOException {
2306: copy.toPhase(JavaSource.Phase.RESOLVED);
2307: TreePath path = copy.getTreeUtilities()
2308: .pathFor(off);
2309: while (path.getLeaf() != path
2310: .getCompilationUnit()) {
2311: Tree tree = path.getLeaf();
2312: Tree parentTree = path.getParentPath()
2313: .getLeaf();
2314: if (parentTree.getKind() == Tree.Kind.NEW_CLASS
2315: && tree.getKind() == Tree.Kind.CLASS) {
2316: GeneratorUtils
2317: .generateAllAbstractMethodImplementations(
2318: copy, path);
2319: break;
2320: }
2321: path = path.getParentPath();
2322: }
2323: }
2324: }).commit();
2325: } catch (Exception ex) {
2326: }
2327: }
2328: if (!params.isEmpty() && text.trim().length() > 1) {
2329: CodeTemplateManager ctm = CodeTemplateManager.get(doc);
2330: if (ctm != null) {
2331: if (position != null)
2332: offset = position.getOffset();
2333: if (toAdd == null)
2334: toAdd = ""; //NOI18N
2335: if (text.startsWith("()" + toAdd)) //NOI18N
2336: c.select(offset, offset + toAdd.length() + 2);
2337: else if (text.startsWith("()")) //NOI18N
2338: c.select(offset, offset + 2);
2339: else
2340: c.setCaretPosition(offset);
2341: StringBuilder sb = new StringBuilder();
2342: sb.append("("); //NOI18N
2343: for (Iterator<ParamDesc> it = params.iterator(); it
2344: .hasNext();) {
2345: ParamDesc paramDesc = it.next();
2346: sb.append("${"); //NOI18N
2347: sb.append(paramDesc.name);
2348: sb.append(" named instanceof="); //NOI18N
2349: sb.append(paramDesc.fullTypeName);
2350: sb.append("}"); //NOI18N
2351: if (it.hasNext())
2352: sb.append(", "); //NOI18N
2353: }
2354: sb.append(")"); //NOI18N
2355: sb.append(toAdd);
2356: ctm.createTemporary(sb.toString()).insert(c);
2357: Completion.get().showToolTip();
2358: }
2359: }
2360: }
2361:
2362: public String toString() {
2363: StringBuilder sb = new StringBuilder();
2364: for (Modifier mod : modifiers) {
2365: sb.append(mod.toString());
2366: sb.append(' ');
2367: }
2368: sb.append(simpleName);
2369: sb.append('('); //NOI18N
2370: for (Iterator<ParamDesc> it = params.iterator(); it
2371: .hasNext();) {
2372: ParamDesc paramDesc = it.next();
2373: sb.append(paramDesc.typeName);
2374: sb.append(' ');
2375: sb.append(paramDesc.name);
2376: if (it.hasNext()) {
2377: sb.append(", "); //NOI18N
2378: }
2379: }
2380: sb.append(')');
2381: return sb.toString();
2382: }
2383: }
2384:
2385: static class DefaultConstructorItem extends JavaCompletionItem {
2386:
2387: private static final String CONSTRUCTOR = "org/netbeans/modules/java/editor/resources/new_constructor_16.png"; //NOI18N
2388: private static final String CONSTRUCTOR_COLOR = "<font color=#b28b00>"; //NOI18N
2389: private static ImageIcon icon;
2390:
2391: private boolean smartType;
2392: private String simpleName;
2393: private boolean isAbstract;
2394: private String sortText;
2395: private String leftText;
2396:
2397: private DefaultConstructorItem(TypeElement elem,
2398: int substitutionOffset, boolean smartType) {
2399: super (substitutionOffset);
2400: this .smartType = smartType;
2401: this .simpleName = elem.getSimpleName().toString();
2402: this .isAbstract = elem.getModifiers().contains(
2403: Modifier.ABSTRACT);
2404: }
2405:
2406: public CharSequence getInsertPrefix() {
2407: return simpleName;
2408: }
2409:
2410: public int getSortPriority() {
2411: return smartType ? 650 - SMART_TYPE : 650;
2412: }
2413:
2414: public CharSequence getSortText() {
2415: if (sortText == null)
2416: sortText = simpleName + "#0#"; //NOI18N
2417: return sortText;
2418: }
2419:
2420: protected String getLeftHtmlText() {
2421: if (leftText == null)
2422: leftText = CONSTRUCTOR_COLOR + simpleName + "()"
2423: + COLOR_END; //NOI18N
2424: return leftText;
2425: }
2426:
2427: protected ImageIcon getIcon() {
2428: if (icon == null)
2429: icon = new ImageIcon(org.openide.util.Utilities
2430: .loadImage(CONSTRUCTOR));
2431: return icon;
2432: }
2433:
2434: protected void substituteText(JTextComponent c, int offset,
2435: int len, String toAdd) {
2436: offset += len;
2437: len = 0;
2438: int semiPos = toAdd != null && toAdd.endsWith(";") ? findPositionForSemicolon(c)
2439: : -2; //NOI18N
2440: if (semiPos > -2)
2441: toAdd = toAdd.length() > 1 ? toAdd.substring(0, toAdd
2442: .length() - 1) : null;
2443: BaseDocument doc = (BaseDocument) c.getDocument();
2444: TokenSequence<JavaTokenId> sequence = SourceUtils
2445: .getJavaTokenSequence(TokenHierarchy.get(doc),
2446: offset);
2447: if (sequence == null || !sequence.moveNext()
2448: && !sequence.movePrevious()) {
2449: sequence.movePrevious();
2450: if (sequence.token().id() == JavaTokenId.THIS
2451: || sequence.token().id() == JavaTokenId.SUPER) {
2452: isAbstract = false;
2453: if (toAdd == null)
2454: toAdd = ";"; //NOI18N
2455: }
2456: sequence.moveNext();
2457: }
2458: String add = isAbstract ? "() {}" : "()"; //NOI18N
2459: if (toAdd != null && !add.startsWith(toAdd))
2460: add += toAdd;
2461: String text = CodeStyle.getDefault(null)
2462: .spaceBeforeMethodCallParen() ? " " : ""; //NOI18N
2463: if (sequence == null) {
2464: text += add;
2465: add = null;
2466: }
2467: boolean added = false;
2468: while (add != null && add.length() > 0) {
2469: String tokenText = sequence.token().text().toString();
2470: if (tokenText.startsWith(add)) {
2471: len = sequence.offset() - offset + add.length();
2472: text += add;
2473: add = null;
2474: } else if (add.startsWith(tokenText)) {
2475: sequence.moveNext();
2476: len = sequence.offset() - offset;
2477: text += add.substring(0, tokenText.length());
2478: add = add.substring(tokenText.length());
2479: added = true;
2480: } else if (sequence.token().id() == JavaTokenId.WHITESPACE
2481: && sequence.token().text().toString().indexOf(
2482: '\n') < 0) {//NOI18N
2483: if (!sequence.moveNext()) {
2484: text += add;
2485: add = null;
2486: }
2487: } else {
2488: if (!added)
2489: text += add;
2490: add = null;
2491: }
2492: }
2493: doc.atomicLock();
2494: Position position = null;
2495: try {
2496: position = doc.createPosition(offset);
2497: Position semiPosition = semiPos > -1 ? doc
2498: .createPosition(semiPos) : null;
2499: doc.remove(offset, len);
2500: offset = position.getOffset();
2501: doc.insertString(offset, text, null);
2502: position = doc.createPosition(offset);
2503: if (semiPosition != null)
2504: doc.insertString(semiPosition.getOffset(), ";",
2505: null); //NOI18N
2506: else if (!isAbstract && "(".equals(toAdd)) //NOI18N
2507: c.setCaretPosition(c.getCaretPosition() - 1);
2508: } catch (BadLocationException e) {
2509: } finally {
2510: doc.atomicUnlock();
2511: }
2512: if (isAbstract && text.trim().length() > 3) {
2513: try {
2514: if (position != null)
2515: offset = position.getOffset();
2516: JavaSource js = JavaSource.forDocument(c
2517: .getDocument());
2518: final int off = offset + text.indexOf('{') + 1;
2519: js.runModificationTask(new Task<WorkingCopy>() {
2520:
2521: public void run(WorkingCopy copy)
2522: throws IOException {
2523: copy.toPhase(JavaSource.Phase.RESOLVED);
2524: TreePath path = copy.getTreeUtilities()
2525: .pathFor(off);
2526: while (path.getLeaf() != path
2527: .getCompilationUnit()) {
2528: Tree tree = path.getLeaf();
2529: Tree parentTree = path.getParentPath()
2530: .getLeaf();
2531: if (parentTree.getKind() == Tree.Kind.NEW_CLASS
2532: && tree.getKind() == Tree.Kind.CLASS) {
2533: GeneratorUtils
2534: .generateAllAbstractMethodImplementations(
2535: copy, path);
2536: break;
2537: }
2538: path = path.getParentPath();
2539: }
2540: }
2541: }).commit();
2542: } catch (IOException ex) {
2543: }
2544: }
2545: }
2546:
2547: public String toString() {
2548: return simpleName + "()";
2549: }
2550: }
2551:
2552: static class ParametersItem extends JavaCompletionItem {
2553:
2554: private static final String PARAMETERS_COLOR = "<font color=#808080>"; //NOI18N
2555: private static final String ACTIVE_PARAMETER_COLOR = "<font color=#000000>"; //NOI18N
2556:
2557: protected ElementHandle<ExecutableElement> elementHandle;
2558: private boolean isDeprecated;
2559: private int activeParamsIndex;
2560: private String simpleName;
2561: private ArrayList<ParamDesc> params;
2562: private String typeName;
2563: private String sortText;
2564: private String leftText;
2565: private String rightText;
2566:
2567: private ParametersItem(ExecutableElement elem,
2568: ExecutableType type, int substitutionOffset,
2569: boolean isDeprecated, int activeParamsIndex) {
2570: super (substitutionOffset);
2571: this .elementHandle = ElementHandle.create(elem);
2572: this .isDeprecated = isDeprecated;
2573: this .activeParamsIndex = activeParamsIndex;
2574: this .simpleName = elem.getKind() == ElementKind.CONSTRUCTOR ? elem
2575: .getEnclosingElement().getSimpleName().toString()
2576: : elem.getSimpleName().toString();
2577: this .params = new ArrayList<ParamDesc>();
2578: Iterator<? extends VariableElement> it = elem
2579: .getParameters().iterator();
2580: Iterator<? extends TypeMirror> tIt = type
2581: .getParameterTypes().iterator();
2582: while (it.hasNext() && tIt.hasNext()) {
2583: TypeMirror tm = tIt.next();
2584: this .params.add(new ParamDesc(tm.toString(), Utilities
2585: .getTypeName(tm, false,
2586: elem.isVarArgs() && !tIt.hasNext())
2587: .toString(), it.next().getSimpleName()
2588: .toString()));
2589: }
2590: TypeMirror retType = type.getReturnType();
2591: this .typeName = Utilities.getTypeName(retType, false)
2592: .toString();
2593: }
2594:
2595: public int getSortPriority() {
2596: return 100 - SMART_TYPE;
2597: }
2598:
2599: public CharSequence getSortText() {
2600: if (sortText == null) {
2601: StringBuilder sortParams = new StringBuilder();
2602: sortParams.append('(');
2603: int cnt = 0;
2604: for (Iterator<ParamDesc> it = params.iterator(); it
2605: .hasNext();) {
2606: ParamDesc param = it.next();
2607: sortParams.append(param.typeName);
2608: if (it.hasNext()) {
2609: sortParams.append(',');
2610: }
2611: cnt++;
2612: }
2613: sortParams.append(')');
2614: sortText = "#" + ((cnt < 10 ? "0" : "") + cnt) + "#"
2615: + sortParams.toString(); //NOI18N
2616: }
2617: return sortText;
2618: }
2619:
2620: public CharSequence getInsertPrefix() {
2621: return ""; //NOI18N
2622: }
2623:
2624: protected String getLeftHtmlText() {
2625: if (leftText == null) {
2626: StringBuilder lText = new StringBuilder();
2627: lText.append(PARAMETERS_COLOR);
2628: if (isDeprecated)
2629: lText.append(STRIKE);
2630: lText.append(simpleName);
2631: if (isDeprecated)
2632: lText.append(STRIKE_END);
2633: lText.append('(');
2634: for (int i = 0; i < params.size(); i++) {
2635: ParamDesc paramDesc = params.get(i);
2636: if (i == activeParamsIndex)
2637: lText.append(COLOR_END).append(
2638: ACTIVE_PARAMETER_COLOR).append(BOLD);
2639: lText.append(escape(paramDesc.typeName));
2640: lText.append(' ');
2641: lText.append(paramDesc.name);
2642: if (i < params.size() - 1)
2643: lText.append(", "); //NOI18N
2644: else
2645: lText.append(BOLD_END).append(COLOR_END)
2646: .append(PARAMETERS_COLOR);
2647: }
2648: lText.append(')');
2649: lText.append(COLOR_END);
2650: return lText.toString();
2651: }
2652: return leftText;
2653: }
2654:
2655: protected String getRightHtmlText() {
2656: if (rightText == null)
2657: rightText = PARAMETERS_COLOR + escape(typeName)
2658: + COLOR_END;
2659: return rightText;
2660: }
2661:
2662: public CompletionTask createDocumentationTask() {
2663: return JavaCompletionProvider.createDocTask(elementHandle);
2664: }
2665:
2666: public boolean instantSubstitution(JTextComponent component) {
2667: return false;
2668: }
2669:
2670: protected void substituteText(final JTextComponent c,
2671: int offset, int len, String toAdd) {
2672: String add = ")"; //NOI18N
2673: if (toAdd != null && !add.startsWith(toAdd))
2674: add += toAdd;
2675: if (params.isEmpty()) {
2676: super .substituteText(c, offset, len, add);
2677: } else {
2678: BaseDocument doc = (BaseDocument) c.getDocument();
2679: String text = ""; //NOI18N
2680: int semiPos = add.endsWith(";") ? findPositionForSemicolon(c)
2681: : -2; //NOI18N
2682: if (semiPos > -2)
2683: add = add.length() > 1 ? add.substring(0, add
2684: .length() - 1) : null;
2685: TokenSequence<JavaTokenId> sequence = SourceUtils
2686: .getJavaTokenSequence(TokenHierarchy.get(doc),
2687: offset + len);
2688: if (sequence == null || !sequence.moveNext()
2689: && !sequence.movePrevious()) {
2690: text += add;
2691: add = null;
2692: }
2693: boolean added = false;
2694: while (add != null && add.length() > 0) {
2695: String tokenText = sequence.token().text()
2696: .toString();
2697: if (tokenText.startsWith(add)) {
2698: len = sequence.offset() - offset + add.length();
2699: text += add;
2700: add = null;
2701: } else if (add.startsWith(tokenText)) {
2702: sequence.moveNext();
2703: len = sequence.offset() - offset;
2704: text += add.substring(0, tokenText.length());
2705: add = add.substring(tokenText.length());
2706: added = true;
2707: } else if (sequence.token().id() == JavaTokenId.WHITESPACE
2708: && sequence.token().text().toString()
2709: .indexOf('\n') < 0) {//NOI18N
2710: if (!sequence.moveNext()) {
2711: text += add;
2712: add = null;
2713: }
2714: } else {
2715: if (!added)
2716: text += add;
2717: add = null;
2718: }
2719: }
2720: doc.atomicLock();
2721: try {
2722: Position semiPosition = semiPos > -1 ? doc
2723: .createPosition(semiPos) : null;
2724: if (len > 0)
2725: doc.remove(offset, len);
2726: if (semiPosition != null)
2727: doc.insertString(semiPosition.getOffset(), ";",
2728: null); //NOI18N
2729: } catch (BadLocationException e) {
2730: // Can't update
2731: } finally {
2732: doc.atomicUnlock();
2733: }
2734: CodeTemplateManager ctm = CodeTemplateManager.get(doc);
2735: if (ctm != null) {
2736: StringBuilder sb = new StringBuilder();
2737: for (int i = activeParamsIndex; i < params.size(); i++) {
2738: ParamDesc paramDesc = params.get(i);
2739: sb.append("${"); //NOI18N
2740: sb.append(paramDesc.name);
2741: sb.append(" named instanceof="); //NOI18N
2742: sb.append(paramDesc.fullTypeName);
2743: sb.append("}"); //NOI18N
2744: if (i < params.size() - 1)
2745: sb.append(", "); //NOI18N
2746: }
2747: if (text.length() > 0)
2748: sb.append(text);
2749: ctm.createTemporary(sb.toString()).insert(c);
2750: Completion.get().showToolTip();
2751: }
2752: }
2753: }
2754:
2755: public String toString() {
2756: StringBuilder sb = new StringBuilder();
2757: sb.append(typeName);
2758: sb.append(' ');
2759: sb.append(simpleName);
2760: sb.append('(');
2761: for (Iterator<ParamDesc> it = params.iterator(); it
2762: .hasNext();) {
2763: ParamDesc paramDesc = it.next();
2764: sb.append(paramDesc.typeName);
2765: sb.append(' ');
2766: sb.append(paramDesc.name);
2767: if (it.hasNext()) {
2768: sb.append(", "); //NOI18N
2769: }
2770: }
2771: sb.append(')');
2772: return sb.toString();
2773: }
2774: }
2775:
2776: static class AnnotationItem extends AnnotationTypeItem {
2777:
2778: private AnnotationItem(TypeElement elem, DeclaredType type,
2779: int substitutionOffset, boolean isDeprecated,
2780: boolean smartType) {
2781: super (elem, type, 0, substitutionOffset, true,
2782: isDeprecated, false, smartType);
2783: }
2784:
2785: public CharSequence getInsertPrefix() {
2786: return "@" + super .getInsertPrefix(); //NOI18N
2787: }
2788:
2789: protected void substituteText(final JTextComponent c,
2790: final int offset, int len, String toAdd) {
2791: final BaseDocument doc = (BaseDocument) c.getDocument();
2792: final StringBuilder text = new StringBuilder();
2793: final int semiPos = toAdd != null && toAdd.endsWith(";") ? findPositionForSemicolon(c)
2794: : -2; //NOI18N
2795: if (semiPos > -2)
2796: toAdd = toAdd.length() > 1 ? toAdd.substring(0, toAdd
2797: .length() - 1) : null;
2798: if (toAdd != null && !toAdd.equals("\n")) {//NOI18N
2799: TokenSequence<JavaTokenId> sequence = SourceUtils
2800: .getJavaTokenSequence(TokenHierarchy.get(doc),
2801: offset + len);
2802: if (sequence == null || !sequence.moveNext()
2803: && !sequence.movePrevious()) {
2804: text.append(toAdd);
2805: toAdd = null;
2806: }
2807: boolean added = false;
2808: while (toAdd != null && toAdd.length() > 0) {
2809: String tokenText = sequence.token().text()
2810: .toString();
2811: if (tokenText.startsWith(toAdd)) {
2812: len = sequence.offset() - offset
2813: + toAdd.length();
2814: text.append(toAdd);
2815: toAdd = null;
2816: } else if (toAdd.startsWith(tokenText)) {
2817: sequence.moveNext();
2818: len = sequence.offset() - offset;
2819: text.append(toAdd.substring(0, tokenText
2820: .length()));
2821: toAdd = toAdd.substring(tokenText.length());
2822: added = true;
2823: } else if (sequence.token().id() == JavaTokenId.WHITESPACE
2824: && sequence.token().text().toString()
2825: .indexOf('\n') < 0) {//NOI18N
2826: if (!sequence.moveNext()) {
2827: text.append(toAdd);
2828: toAdd = null;
2829: }
2830: } else {
2831: if (!added)
2832: text.append(toAdd);
2833: toAdd = null;
2834: }
2835: }
2836: }
2837: final int finalLen = len;
2838: JavaSource js = JavaSource.forDocument(doc);
2839: try {
2840: js.runUserActionTask(new Task<CompilationController>() {
2841:
2842: public void run(CompilationController controller)
2843: throws IOException {
2844: controller.toPhase(JavaSource.Phase.RESOLVED);
2845: DeclaredType type = typeHandle
2846: .resolve(controller);
2847: // Update the text
2848: doc.atomicLock();
2849: try {
2850: Position semiPosition = semiPos > -1 ? doc
2851: .createPosition(semiPos) : null;
2852: TreePath tp = controller.getTreeUtilities()
2853: .pathFor(offset);
2854: text.insert(0, "@"
2855: + AutoImport.resolveImport(
2856: controller, tp, type)); //NOI18N
2857: String textToReplace = doc.getText(offset,
2858: finalLen);
2859: if (textToReplace.contentEquals(text))
2860: return;
2861: doc.remove(offset, finalLen);
2862: doc.insertString(offset, text.toString(),
2863: null);
2864: if (semiPosition != null)
2865: doc.insertString(semiPosition
2866: .getOffset(), ";", null); //NOI18N
2867: } catch (BadLocationException e) {
2868: // Can't update
2869: } finally {
2870: doc.atomicUnlock();
2871: }
2872: }
2873: }, true);
2874: } catch (IOException ioe) {
2875: }
2876: }
2877: }
2878:
2879: static class AttributeItem extends JavaCompletionItem {
2880:
2881: private static final String ATTRIBUTE = "org/netbeans/modules/java/editor/resources/attribute_16.png"; // NOI18N
2882: private static final String ATTRIBUTE_COLOR = "<font color=#404040>"; //NOI18N
2883: private static ImageIcon icon;
2884:
2885: private ElementHandle<ExecutableElement> elementHandle;
2886: private boolean isDeprecated;
2887: private String simpleName;
2888: private String typeName;
2889: private String defaultValue;
2890: private String leftText;
2891: private String rightText;
2892:
2893: private AttributeItem(ExecutableElement elem,
2894: ExecutableType type, int substitutionOffset,
2895: boolean isDeprecated) {
2896: super (substitutionOffset);
2897: this .elementHandle = ElementHandle.create(elem);
2898: this .isDeprecated = isDeprecated;
2899: this .simpleName = elem.getSimpleName().toString();
2900: this .typeName = Utilities.getTypeName(type.getReturnType(),
2901: false).toString();
2902: AnnotationValue value = elem.getDefaultValue();
2903: this .defaultValue = value != null ? value.toString() : null;
2904: }
2905:
2906: public int getSortPriority() {
2907: return 100;
2908: }
2909:
2910: public CharSequence getSortText() {
2911: return simpleName;
2912: }
2913:
2914: public CharSequence getInsertPrefix() {
2915: return simpleName + "="; //NOI18N
2916: }
2917:
2918: public CompletionTask createDocumentationTask() {
2919: return JavaCompletionProvider.createDocTask(elementHandle);
2920: }
2921:
2922: protected ImageIcon getIcon() {
2923: if (icon == null)
2924: icon = new ImageIcon(org.openide.util.Utilities
2925: .loadImage(ATTRIBUTE));
2926: return icon;
2927: }
2928:
2929: protected String getLeftHtmlText() {
2930: if (leftText == null) {
2931: StringBuilder sb = new StringBuilder();
2932: sb.append(ATTRIBUTE_COLOR);
2933: if (defaultValue == null)
2934: sb.append(BOLD);
2935: if (isDeprecated)
2936: sb.append(STRIKE);
2937: sb.append(simpleName);
2938: if (isDeprecated)
2939: sb.append(STRIKE_END);
2940: if (defaultValue == null) {
2941: sb.append(BOLD_END);
2942: } else {
2943: sb.append(" = "); //NOI18N
2944: sb.append(defaultValue);
2945: }
2946: sb.append(COLOR_END);
2947: leftText = sb.toString();
2948: }
2949: return leftText;
2950: }
2951:
2952: protected String getRightHtmlText() {
2953: if (rightText == null)
2954: rightText = escape(typeName);
2955: return rightText;
2956: }
2957:
2958: public String toString() {
2959: return simpleName;
2960: }
2961: }
2962:
2963: static class StaticMemberItem extends JavaCompletionItem {
2964:
2965: private static final String FIELD_ST_PUBLIC = "org/netbeans/modules/editor/resources/completion/field_static_16.png"; //NOI18N
2966: private static final String FIELD_ST_PROTECTED = "org/netbeans/modules/editor/resources/completion/field_static_protected_16.png"; //NOI18N
2967: private static final String FIELD_ST_PACKAGE = "org/netbeans/modules/editor/resources/completion/field_static_package_private_16.png"; //NOI18N
2968: private static final String FIELD_COLOR = "<font color=#0000b2>"; //NOI18N
2969: private static final String METHOD_ST_PUBLIC = "org/netbeans/modules/editor/resources/completion/method_static_16.png"; //NOI18N
2970: private static final String METHOD_ST_PROTECTED = "org/netbeans/modules/editor/resources/completion/method_static_protected_16.png"; //NOI18N
2971: private static final String METHOD_ST_PACKAGE = "org/netbeans/modules/editor/resources/completion/method_static_package_private_16.png"; //NOI18N
2972: private static final String METHOD_COLOR = "<font color=#7c0000>"; //NOI18N
2973: private static final String PARAMETER_NAME_COLOR = "<font color=#b200b2>"; //NOI18N
2974: private static ImageIcon icon[][] = new ImageIcon[2][3];
2975:
2976: private TypeMirrorHandle<DeclaredType> typeHandle;
2977: private ElementHandle<Element> memberElementHandle;
2978: private boolean isDeprecated;
2979: private String typeName;
2980: private String memberName;
2981: private String memberTypeName;
2982: private Set<Modifier> modifiers;
2983: private List<ParamDesc> params;
2984: private String sortText;
2985: private String leftText;
2986: private String rightText;
2987:
2988: private StaticMemberItem(DeclaredType type, Element memberElem,
2989: TypeMirror memberType, int substitutionOffset,
2990: boolean isDeprecated) {
2991: super (substitutionOffset);
2992: this .typeHandle = TypeMirrorHandle.create(type);
2993: this .memberElementHandle = ElementHandle.create(memberElem);
2994: this .isDeprecated = isDeprecated;
2995: this .typeName = Utilities.getTypeName(type, false)
2996: .toString();
2997: this .memberName = memberElem.getSimpleName().toString();
2998: this .memberTypeName = Utilities.getTypeName(
2999: memberElem.getKind().isField() ? memberType
3000: : ((ExecutableType) memberType)
3001: .getReturnType(), false).toString();
3002: this .modifiers = memberElem.getModifiers();
3003: if (!memberElem.getKind().isField()) {
3004: this .params = new ArrayList<ParamDesc>();
3005: Iterator<? extends VariableElement> it = ((ExecutableElement) memberElem)
3006: .getParameters().iterator();
3007: Iterator<? extends TypeMirror> tIt = ((ExecutableType) memberType)
3008: .getParameterTypes().iterator();
3009: while (it.hasNext() && tIt.hasNext()) {
3010: TypeMirror tm = tIt.next();
3011: this .params.add(new ParamDesc(tm.toString(),
3012: Utilities.getTypeName(
3013: tm,
3014: false,
3015: ((ExecutableElement) memberElem)
3016: .isVarArgs()
3017: && !tIt.hasNext())
3018: .toString(), it.next()
3019: .getSimpleName().toString()));
3020: }
3021: }
3022: }
3023:
3024: public int getSortPriority() {
3025: return (params == null ? 700 : 750) - SMART_TYPE;
3026: }
3027:
3028: public CharSequence getSortText() {
3029: if (sortText == null) {
3030: if (params == null) {
3031: sortText = memberName + "#" + typeName; //NOI18N
3032: } else {
3033: StringBuilder sortParams = new StringBuilder();
3034: sortParams.append('(');
3035: int cnt = 0;
3036: for (Iterator<ParamDesc> it = params.iterator(); it
3037: .hasNext();) {
3038: ParamDesc paramDesc = it.next();
3039: sortParams.append(paramDesc.typeName);
3040: if (it.hasNext()) {
3041: sortParams.append(',');
3042: }
3043: cnt++;
3044: }
3045: sortParams.append(')');
3046: sortText = memberName + "#"
3047: + ((cnt < 10 ? "0" : "") + cnt) + "#"
3048: + sortParams.toString() + "#" + typeName; //NOI18N
3049: }
3050: }
3051: return sortText;
3052: }
3053:
3054: public CharSequence getInsertPrefix() {
3055: return typeName + "." + memberName; //NOI18N
3056: }
3057:
3058: public CompletionTask createDocumentationTask() {
3059: return JavaCompletionProvider
3060: .createDocTask(memberElementHandle);
3061: }
3062:
3063: protected String getLeftHtmlText() {
3064: if (leftText == null) {
3065: StringBuilder lText = new StringBuilder();
3066: lText
3067: .append(memberElementHandle.getKind().isField() ? FIELD_COLOR
3068: : METHOD_COLOR);
3069: lText.append(escape(typeName));
3070: lText.append('.');
3071: if (isDeprecated)
3072: lText.append(STRIKE);
3073: lText.append(memberName);
3074: if (isDeprecated)
3075: lText.append(STRIKE_END);
3076: lText.append(COLOR_END);
3077: if (params != null) {
3078: lText.append('(');
3079: for (Iterator<ParamDesc> it = params.iterator(); it
3080: .hasNext();) {
3081: ParamDesc paramDesc = it.next();
3082: lText.append(escape(paramDesc.typeName));
3083: lText.append(' '); //NOI18N
3084: lText.append(PARAMETER_NAME_COLOR);
3085: lText.append(paramDesc.name);
3086: lText.append(COLOR_END);
3087: if (it.hasNext()) {
3088: lText.append(", "); //NOI18N
3089: }
3090: }
3091: lText.append(')');
3092: }
3093: leftText = lText.toString();
3094: }
3095: return leftText;
3096: }
3097:
3098: protected String getRightHtmlText() {
3099: if (rightText == null)
3100: rightText = escape(memberTypeName);
3101: return rightText;
3102: }
3103:
3104: protected ImageIcon getIcon() {
3105: int level = getProtectionLevel(modifiers);
3106: boolean isField = memberElementHandle.getKind().isField();
3107: ImageIcon cachedIcon = icon[isField ? 0 : 1][level - 1];
3108: if (cachedIcon != null)
3109: return cachedIcon;
3110:
3111: String iconPath = null;
3112: if (isField) {
3113: switch (level) {
3114: case PACKAGE_LEVEL:
3115: iconPath = FIELD_ST_PACKAGE;
3116: break;
3117:
3118: case PROTECTED_LEVEL:
3119: iconPath = FIELD_ST_PROTECTED;
3120: break;
3121:
3122: case PUBLIC_LEVEL:
3123: iconPath = FIELD_ST_PUBLIC;
3124: break;
3125: }
3126: } else {
3127: switch (level) {
3128: case PACKAGE_LEVEL:
3129: iconPath = METHOD_ST_PACKAGE;
3130: break;
3131:
3132: case PROTECTED_LEVEL:
3133: iconPath = METHOD_ST_PROTECTED;
3134: break;
3135:
3136: case PUBLIC_LEVEL:
3137: iconPath = METHOD_ST_PUBLIC;
3138: break;
3139: }
3140: }
3141: if (iconPath == null)
3142: return null;
3143: ImageIcon newIcon = new ImageIcon(
3144: org.openide.util.Utilities.loadImage(iconPath));
3145: icon[isField ? 0 : 1][level - 1] = newIcon;
3146: return newIcon;
3147: }
3148:
3149: protected void substituteText(final JTextComponent c,
3150: final int offset, int len, String toAdd) {
3151: final BaseDocument doc = (BaseDocument) c.getDocument();
3152: final StringBuilder text = new StringBuilder();
3153: final int semiPos = toAdd != null && toAdd.endsWith(";") ? findPositionForSemicolon(c)
3154: : -2; //NOI18N
3155: if (semiPos > -2)
3156: toAdd = toAdd.length() > 1 ? toAdd.substring(0, toAdd
3157: .length() - 1) : null;
3158: if (toAdd != null && !toAdd.equals("\n")) { //NOI18N
3159: TokenSequence<JavaTokenId> sequence = SourceUtils
3160: .getJavaTokenSequence(TokenHierarchy.get(doc),
3161: offset + len);
3162: if (sequence == null || !sequence.moveNext()
3163: && !sequence.movePrevious()) {
3164: text.append(toAdd);
3165: toAdd = null;
3166: }
3167: boolean added = false;
3168: while (toAdd != null && toAdd.length() > 0) {
3169: String tokenText = sequence.token().text()
3170: .toString();
3171: if (tokenText.startsWith(toAdd)) {
3172: len = sequence.offset() - offset
3173: + toAdd.length();
3174: text.append(toAdd);
3175: toAdd = null;
3176: } else if (toAdd.startsWith(tokenText)) {
3177: sequence.moveNext();
3178: len = sequence.offset() - offset;
3179: text.append(toAdd.substring(0, tokenText
3180: .length()));
3181: toAdd = toAdd.substring(tokenText.length());
3182: added = true;
3183: } else if (sequence.token().id() == JavaTokenId.WHITESPACE
3184: && sequence.token().text().toString()
3185: .indexOf('\n') < 0) {//NOI18N
3186: if (!sequence.moveNext()) {
3187: text.append(toAdd);
3188: toAdd = null;
3189: }
3190: } else {
3191: if (!added)
3192: text.append(toAdd);
3193: toAdd = null;
3194: }
3195: }
3196: }
3197: final int finalLen = len;
3198: JavaSource js = JavaSource.forDocument(doc);
3199: try {
3200: js.runUserActionTask(new Task<CompilationController>() {
3201:
3202: public void run(CompilationController controller)
3203: throws IOException {
3204: controller.toPhase(JavaSource.Phase.RESOLVED);
3205: DeclaredType type = typeHandle
3206: .resolve(controller);
3207: StringBuilder sb = new StringBuilder();
3208: int cnt = 1;
3209: sb.append("${PAR#"); //NOI18N
3210: sb.append(cnt++);
3211: sb.append(" type=\""); //NOI18N
3212: sb.append(((TypeElement) type.asElement())
3213: .getQualifiedName());
3214: sb.append("\" default=\""); //NOI18N
3215: sb.append(((TypeElement) type.asElement())
3216: .getSimpleName());
3217: sb.append("\" editable=false}"); //NOI18N
3218: Iterator<? extends TypeMirror> tas = type
3219: .getTypeArguments().iterator();
3220: if (tas.hasNext()) {
3221: sb.append('<'); //NOI18N
3222: while (tas.hasNext()) {
3223: TypeMirror ta = tas.next();
3224: sb.append("${PAR#"); //NOI18N
3225: sb.append(cnt++);
3226: if (ta.getKind() == TypeKind.TYPEVAR) {
3227: sb.append(" type=\""); //NOI18N
3228: ta = ((TypeVariable) ta)
3229: .getUpperBound();
3230: sb.append(Utilities.getTypeName(ta,
3231: true));
3232: sb.append("\" default=\""); //NOI18N
3233: sb.append(Utilities.getTypeName(ta,
3234: false));
3235: sb.append("\"}"); //NOI18N
3236: } else if (ta.getKind() == TypeKind.WILDCARD) {
3237: sb.append(" type=\""); //NOI18N
3238: TypeMirror bound = ((WildcardType) ta)
3239: .getExtendsBound();
3240: if (bound == null)
3241: bound = ((WildcardType) ta)
3242: .getSuperBound();
3243: sb.append(bound != null ? Utilities
3244: .getTypeName(bound, true)
3245: : "Object"); //NOI18N
3246: sb.append("\" default=\""); //NOI18N
3247: sb.append(bound != null ? Utilities
3248: .getTypeName(bound, false)
3249: : "Object"); //NOI18N
3250: sb.append("\"}"); //NOI18N
3251: } else if (ta.getKind() == TypeKind.ERROR) {
3252: sb.append(" default=\""); //NOI18N
3253: sb.append(((ErrorType) ta)
3254: .asElement()
3255: .getSimpleName());
3256: sb.append("\"}"); //NOI18N
3257: } else {
3258: sb.append(" type=\""); //NOI18N
3259: sb.append(Utilities.getTypeName(ta,
3260: true));
3261: sb.append("\" default=\""); //NOI18N
3262: sb.append(Utilities.getTypeName(ta,
3263: false));
3264: sb.append("\" editable=false}"); //NOI18N
3265: }
3266: if (tas.hasNext())
3267: sb.append(", "); //NOI18N
3268: }
3269: sb.append('>'); //NOI18N
3270: }
3271: sb.append('.'); //NOI18N
3272: sb.append(memberName);
3273: if (params != null) {
3274: sb.append("("); //NOI18N
3275: for (Iterator<ParamDesc> it = params
3276: .iterator(); it.hasNext();) {
3277: ParamDesc paramDesc = it.next();
3278: sb.append("${"); //NOI18N
3279: sb.append(paramDesc.name);
3280: sb.append(" named instanceof="); //NOI18N
3281: sb.append(paramDesc.fullTypeName);
3282: sb.append("}"); //NOI18N
3283: if (it.hasNext())
3284: sb.append(", "); //NOI18N
3285: }
3286: sb.append(")");//NOI18N
3287: }
3288: sb.append(text);
3289: doc.atomicLock();
3290: try {
3291: Position semiPosition = semiPos > -1 ? doc
3292: .createPosition(semiPos) : null;
3293: if (finalLen > 0)
3294: doc.remove(offset, finalLen);
3295: if (semiPosition != null)
3296: doc.insertString(semiPosition
3297: .getOffset(), ";", null); //NOI18N
3298: } catch (BadLocationException e) {
3299: // Can't update
3300: } finally {
3301: doc.atomicUnlock();
3302: }
3303: CodeTemplateManager ctm = CodeTemplateManager
3304: .get(doc);
3305: if (ctm != null) {
3306: ctm.createTemporary(sb.toString())
3307: .insert(c);
3308: }
3309: }
3310: }, true);
3311: } catch (IOException ioe) {
3312: }
3313: }
3314:
3315: public String toString() {
3316: StringBuilder sb = new StringBuilder();
3317: for (Modifier mod : modifiers) {
3318: sb.append(mod.toString());
3319: sb.append(' '); // NOI18N
3320: }
3321: sb.append(memberTypeName);
3322: sb.append(' ');
3323: sb.append(typeName);
3324: sb.append('.');
3325: sb.append(memberName);
3326: if (params != null) {
3327: sb.append('('); //NOI18N
3328: for (Iterator<ParamDesc> it = params.iterator(); it
3329: .hasNext();) {
3330: ParamDesc paramDesc = it.next();
3331: sb.append(paramDesc.typeName);
3332: sb.append(' ');
3333: sb.append(paramDesc.name);
3334: if (it.hasNext()) {
3335: sb.append(", "); //NOI18N
3336: }
3337: }
3338: sb.append(')');
3339: }
3340: return sb.toString();
3341: }
3342: }
3343:
3344: static class InitializeAllConstructorItem extends
3345: JavaCompletionItem {
3346:
3347: private static final String CONSTRUCTOR_PUBLIC = "org/netbeans/modules/java/editor/resources/new_constructor_16.png"; //NOI18N
3348: private static final String CONSTRUCTOR_COLOR = "<font color=#b28b00>"; //NOI18N
3349: private static final String PARAMETER_NAME_COLOR = "<font color=#b200b2>"; //NOI18N
3350: private static ImageIcon icon;
3351:
3352: private List<ElementHandle<VariableElement>> fieldHandles;
3353: private ElementHandle<TypeElement> parentHandle;
3354: private String simpleName;
3355: private List<ParamDesc> params;
3356: private String sortText;
3357: private String leftText;
3358:
3359: private InitializeAllConstructorItem(
3360: Iterable<? extends VariableElement> fields,
3361: TypeElement parent, int substitutionOffset) {
3362: super (substitutionOffset);
3363: this .fieldHandles = new ArrayList<ElementHandle<VariableElement>>();
3364: this .parentHandle = ElementHandle.create(parent);
3365: this .params = new ArrayList<ParamDesc>();
3366: for (VariableElement ve : fields) {
3367: this .fieldHandles.add(ElementHandle.create(ve));
3368: this .params.add(new ParamDesc(null, Utilities
3369: .getTypeName(ve.asType(), false).toString(), ve
3370: .getSimpleName().toString()));
3371: }
3372: this .simpleName = parent.getSimpleName().toString();
3373: }
3374:
3375: public int getSortPriority() {
3376: return 400;
3377: }
3378:
3379: public CharSequence getSortText() {
3380: if (sortText == null) {
3381: StringBuilder sortParams = new StringBuilder();
3382: sortParams.append('('); //NOI18N
3383: int cnt = 0;
3384: for (Iterator<ParamDesc> it = params.iterator(); it
3385: .hasNext();) {
3386: ParamDesc paramDesc = it.next();
3387: sortParams.append(paramDesc.typeName);
3388: if (it.hasNext()) {
3389: sortParams.append(','); //NOI18N
3390: }
3391: cnt++;
3392: }
3393: sortParams.append(')'); //NOI18N
3394: sortText = simpleName + "#"
3395: + ((cnt < 10 ? "0" : "") + cnt) + "#"
3396: + sortParams.toString(); //NOI18N
3397: }
3398: return sortText;
3399: }
3400:
3401: protected String getLeftHtmlText() {
3402: if (leftText == null) {
3403: StringBuilder lText = new StringBuilder();
3404: lText.append(CONSTRUCTOR_COLOR);
3405: lText.append(simpleName);
3406: lText.append(COLOR_END);
3407: lText.append('('); //NOI18N
3408: for (Iterator<ParamDesc> it = params.iterator(); it
3409: .hasNext();) {
3410: ParamDesc paramDesc = it.next();
3411: lText.append(escape(paramDesc.typeName));
3412: lText.append(' '); //NOI18N
3413: lText.append(PARAMETER_NAME_COLOR);
3414: lText.append(paramDesc.name);
3415: lText.append(COLOR_END);
3416: if (it.hasNext()) {
3417: lText.append(", "); //NOI18N
3418: }
3419: }
3420: lText.append(") - "); //NOI18N
3421: lText.append(GENERATE_TEXT);
3422: leftText = lText.toString();
3423: }
3424: return leftText;
3425: }
3426:
3427: protected ImageIcon getIcon() {
3428: if (icon == null)
3429: icon = new ImageIcon(org.openide.util.Utilities
3430: .loadImage(CONSTRUCTOR_PUBLIC));
3431: return icon;
3432: }
3433:
3434: public CharSequence getInsertPrefix() {
3435: return simpleName;
3436: }
3437:
3438: protected void substituteText(final JTextComponent c,
3439: final int offset, final int len, String toAdd) {
3440: BaseDocument doc = (BaseDocument) c.getDocument();
3441: if (len > 0) {
3442: doc.atomicLock();
3443: try {
3444: doc.remove(offset, len);
3445: } catch (BadLocationException e) {
3446: // Can't update
3447: } finally {
3448: doc.atomicUnlock();
3449: }
3450: }
3451: try {
3452: JavaSource js = JavaSource.forDocument(c.getDocument());
3453: js.runModificationTask(new Task<WorkingCopy>() {
3454:
3455: public void run(WorkingCopy copy)
3456: throws IOException {
3457: copy.toPhase(JavaSource.Phase.PARSED);
3458: TreePath tp = copy.getTreeUtilities().pathFor(
3459: offset);
3460: if (tp.getLeaf().getKind() == Tree.Kind.CLASS) {
3461: TypeElement parent = parentHandle
3462: .resolve(copy);
3463: ArrayList<VariableElement> fieldElements = new ArrayList<VariableElement>();
3464: for (ElementHandle<? extends Element> handle : fieldHandles)
3465: fieldElements
3466: .add((VariableElement) handle
3467: .resolve(copy));
3468: int idx = 0;
3469: for (Tree tree : ((ClassTree) tp.getLeaf())
3470: .getMembers()) {
3471: if (copy
3472: .getTrees()
3473: .getSourcePositions()
3474: .getStartPosition(
3475: tp.getCompilationUnit(),
3476: tree) < offset)
3477: idx++;
3478: else
3479: break;
3480: }
3481:
3482: TreeMaker make = copy.getTreeMaker();
3483: ClassTree clazz = (ClassTree) tp.getLeaf();
3484: GeneratorUtilities gu = GeneratorUtilities
3485: .get(copy);
3486: ClassTree decl = make.insertClassMember(
3487: clazz, idx,
3488: gu.createConstructor(parent,
3489: fieldElements, null)); //NOI18N
3490:
3491: copy.rewrite(clazz, decl);
3492: }
3493: }
3494: }).commit();
3495: } catch (IOException ex) {
3496: }
3497: }
3498:
3499: public String toString() {
3500: StringBuilder sb = new StringBuilder();
3501: sb.append("public "); //NOI18N
3502: sb.append(simpleName);
3503: sb.append('('); //NOI18N
3504: for (Iterator<ParamDesc> it = params.iterator(); it
3505: .hasNext();) {
3506: ParamDesc paramDesc = it.next();
3507: sb.append(paramDesc.typeName);
3508: sb.append(' '); //NOI18N
3509: sb.append(paramDesc.name);
3510: if (it.hasNext()) {
3511: sb.append(", "); //NOI18N
3512: }
3513: }
3514: sb.append(") - "); //NOI18N
3515: sb.append(GENERATE_TEXT);
3516: return sb.toString();
3517: }
3518:
3519: public boolean instantSubstitution(JTextComponent component) {
3520: return false; //no instant substitution for create constructor item
3521: }
3522: }
3523:
3524: private static final int PUBLIC_LEVEL = 3;
3525: private static final int PROTECTED_LEVEL = 2;
3526: private static final int PACKAGE_LEVEL = 1;
3527: private static final int PRIVATE_LEVEL = 0;
3528:
3529: private static int getProtectionLevel(Set<Modifier> modifiers) {
3530: if (modifiers.contains(Modifier.PUBLIC))
3531: return PUBLIC_LEVEL;
3532: if (modifiers.contains(Modifier.PROTECTED))
3533: return PROTECTED_LEVEL;
3534: if (modifiers.contains(Modifier.PRIVATE))
3535: return PRIVATE_LEVEL;
3536: return PACKAGE_LEVEL;
3537: }
3538:
3539: private static String escape(String s) {
3540: if (s != null) {
3541: try {
3542: return XMLUtil.toAttributeValue(s);
3543: } catch (Exception ex) {
3544: }
3545: }
3546: return s;
3547: }
3548:
3549: private static int findPositionForSemicolon(JTextComponent c) {
3550: final int[] ret = new int[] { -2 };
3551: final int offset = c.getSelectionEnd();
3552: try {
3553: JavaSource js = JavaSource.forDocument(c.getDocument());
3554: js.runUserActionTask(new Task<CompilationController>() {
3555:
3556: public void run(CompilationController controller)
3557: throws Exception {
3558: controller.toPhase(JavaSource.Phase.PARSED);
3559: Tree t = null;
3560: TreePath tp = controller.getTreeUtilities()
3561: .pathFor(offset);
3562: while (t == null && tp != null) {
3563: switch (tp.getLeaf().getKind()) {
3564: case EXPRESSION_STATEMENT:
3565: ExpressionTree expr = ((ExpressionStatementTree) tp
3566: .getLeaf()).getExpression();
3567: if (expr != null
3568: && expr.getKind() == Tree.Kind.ERRONEOUS)
3569: break;
3570: case IMPORT:
3571: t = tp.getLeaf();
3572: break;
3573: case RETURN:
3574: t = ((ReturnTree) tp.getLeaf())
3575: .getExpression();
3576: break;
3577: case THROW:
3578: t = ((ThrowTree) tp.getLeaf())
3579: .getExpression();
3580: break;
3581: }
3582: tp = tp.getParentPath();
3583: }
3584: if (t != null) {
3585: SourcePositions sp = controller.getTrees()
3586: .getSourcePositions();
3587: int endPos = (int) sp.getEndPosition(tp
3588: .getCompilationUnit(), t);
3589: TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(
3590: controller, offset, endPos);
3591: if (ts != null) {
3592: ret[0] = ts.token().id() == JavaTokenId.SEMICOLON ? -1
3593: : ts.offset() + ts.token().length();
3594: }
3595: } else {
3596: TokenSequence<JavaTokenId> ts = controller
3597: .getTokenHierarchy().tokenSequence(
3598: JavaTokenId.language());
3599: ts.move(offset);
3600: if (ts.moveNext()
3601: && ts.token().id() == JavaTokenId.SEMICOLON)
3602: ret[0] = -1;
3603: }
3604: }
3605: }, true);
3606: } catch (IOException ex) {
3607: }
3608: return ret[0];
3609: }
3610:
3611: private static TokenSequence<JavaTokenId> findLastNonWhitespaceToken(
3612: CompilationController controller, int startPos, int endPos) {
3613: TokenSequence<JavaTokenId> ts = controller.getTokenHierarchy()
3614: .tokenSequence(JavaTokenId.language());
3615: ts.move(endPos);
3616: while (ts.movePrevious()) {
3617: int offset = ts.offset();
3618: if (offset < startPos)
3619: return null;
3620: switch (ts.token().id()) {
3621: case WHITESPACE:
3622: case LINE_COMMENT:
3623: case BLOCK_COMMENT:
3624: case JAVADOC_COMMENT:
3625: break;
3626: default:
3627: return ts;
3628: }
3629: }
3630: return null;
3631: }
3632:
3633: static class ParamDesc {
3634: private String fullTypeName;
3635: private String typeName;
3636: private String name;
3637:
3638: public ParamDesc(String fullTypeName, String typeName,
3639: String name) {
3640: this.fullTypeName = fullTypeName;
3641: this.typeName = typeName;
3642: this.name = name;
3643: }
3644: }
3645: }
|