001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * Portions Copyrighted 2007 Sun Microsystems, Inc.
027: */
028: package org.netbeans.modules.java.hints.errors;
029:
030: import com.sun.source.tree.ClassTree;
031: import com.sun.source.tree.VariableTree;
032: import java.io.IOException;
033: import java.util.Set;
034: import java.util.logging.Level;
035: import javax.lang.model.element.Modifier;
036: import javax.lang.model.element.TypeElement;
037: import javax.lang.model.type.TypeKind;
038: import javax.lang.model.type.TypeMirror;
039: import org.netbeans.api.java.source.ModificationResult;
040: import org.netbeans.api.java.source.Task;
041: import org.netbeans.api.java.source.ClasspathInfo;
042: import org.netbeans.api.java.source.CompilationInfo;
043: import org.netbeans.api.java.source.ElementHandle;
044: import org.netbeans.api.java.source.GeneratorUtilities;
045: import org.netbeans.api.java.source.JavaSource;
046: import org.netbeans.api.java.source.JavaSource.Phase;
047: import org.netbeans.api.java.source.SourceUtils;
048: import org.netbeans.api.java.source.TreeMaker;
049: import org.netbeans.api.java.source.TypeMirrorHandle;
050: import org.netbeans.api.java.source.WorkingCopy;
051: import org.netbeans.modules.java.hints.infrastructure.ErrorHintsProvider;
052: import org.netbeans.spi.editor.hints.ChangeInfo;
053: import org.netbeans.spi.editor.hints.Fix;
054: import org.openide.filesystems.FileObject;
055: import org.openide.util.NbBundle;
056:
057: /**
058: *
059: * @author Jan Lahoda
060: */
061: public final class CreateFieldFix implements Fix {
062:
063: private FileObject targetFile;
064: private ElementHandle<TypeElement> target;
065: private TypeMirrorHandle proposedType;
066: private ClasspathInfo cpInfo;
067: private Set<Modifier> modifiers;
068:
069: private String name;
070: private String inFQN;
071:
072: public CreateFieldFix(CompilationInfo info, String name,
073: Set<Modifier> modifiers, TypeElement target,
074: TypeMirror proposedType, FileObject targetFile) {
075: this .name = name;
076: this .inFQN = target.getQualifiedName().toString();
077: this .cpInfo = info.getClasspathInfo();
078: this .modifiers = modifiers;
079: this .targetFile = targetFile;
080: this .target = ElementHandle.create(target);
081: if (proposedType.getKind() == TypeKind.NULL) {
082: proposedType = info.getElements().getTypeElement(
083: "java.lang.Object").asType(); // NOI18N
084: }
085: this .proposedType = TypeMirrorHandle.create(proposedType);
086: }
087:
088: public String getText() {
089: return NbBundle.getMessage(CreateFieldFix.class,
090: "LBL_FIX_Create_Field", name, inFQN);
091: }
092:
093: public ChangeInfo implement() throws IOException {
094: //use the original cp-info so it is "sure" that the proposedType can be resolved:
095: JavaSource js = JavaSource.create(cpInfo, targetFile);
096:
097: ModificationResult diff = js
098: .runModificationTask(new Task<WorkingCopy>() {
099: public void run(final WorkingCopy working)
100: throws IOException {
101: working.toPhase(Phase.RESOLVED);
102: TypeElement targetType = target
103: .resolve(working);
104:
105: if (targetType == null) {
106: ErrorHintsProvider.LOG.log(Level.INFO,
107: "Cannot resolve target."); // NOI18N
108: return;
109: }
110:
111: ClassTree targetTree = working.getTrees()
112: .getTree(targetType);
113:
114: if (targetTree == null) {
115: ErrorHintsProvider.LOG.log(Level.INFO,
116: "Cannot resolve target tree: "
117: + targetType
118: .getQualifiedName()
119: + "."); // NOI18N
120: return;
121: }
122:
123: TypeMirror proposedType = CreateFieldFix.this .proposedType
124: .resolve(working);
125:
126: if (proposedType == null) {
127: ErrorHintsProvider.LOG.log(Level.INFO,
128: "Cannot resolve proposed type."); // NOI18N
129: return;
130: }
131:
132: TreeMaker make = working.getTreeMaker();
133: TypeMirror tm = proposedType;
134: VariableTree var = null;
135:
136: if (tm.getKind() == TypeKind.DECLARED
137: || tm.getKind() == TypeKind.ARRAY) {
138: var = make.Variable(make
139: .Modifiers(modifiers), name, make
140: .Type(tm), null);
141: }
142:
143: if (tm.getKind().isPrimitive()) {
144: var = make.Variable(make
145: .Modifiers(modifiers), name, make
146: .Type(tm), null);
147: }
148:
149: assert var != null : tm.getKind();
150: ClassTree decl = GeneratorUtilities
151: .get(working).insertClassMember(
152: targetTree, var);
153: working.rewrite(targetTree, decl);
154: }
155: });
156:
157: return Utilities.commitAndComputeChangeInfo(targetFile, diff);
158: }
159:
160: String toDebugString(CompilationInfo info) {
161: return "CreateFieldFix:" + name + ":"
162: + target.getQualifiedName() + ":"
163: + proposedType.resolve(info).toString() + ":"
164: + modifiers; // NOI18N
165: }
166:
167: @Override
168: public boolean equals(Object obj) {
169: if (obj == null) {
170: return false;
171: }
172: if (getClass() != obj.getClass()) {
173: return false;
174: }
175: final CreateFieldFix other = (CreateFieldFix) obj;
176: if (this .target != other.target
177: && (this .target == null || !this .target
178: .equals(other.target))) {
179: return false;
180: }
181: if (this .modifiers != other.modifiers
182: && (this .modifiers == null || !this .modifiers
183: .equals(other.modifiers))) {
184: return false;
185: }
186: if (this .name != other.name
187: && (this .name == null || !this .name.equals(other.name))) {
188: return false;
189: }
190: return true;
191: }
192:
193: @Override
194: public int hashCode() {
195: int hash = 5;
196: hash = 79 * hash
197: + (this .target != null ? this .target.hashCode() : 0);
198: hash = 79
199: * hash
200: + (this .modifiers != null ? this .modifiers.hashCode()
201: : 0);
202: hash = 79 * hash
203: + (this .name != null ? this .name.hashCode() : 0);
204: return hash;
205: }
206:
207: }
|