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: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.java.hints.errors;
042:
043: import com.sun.source.tree.ModifiersTree;
044: import com.sun.source.tree.Tree;
045: import com.sun.source.tree.Tree.Kind;
046: import com.sun.source.tree.VariableTree;
047: import com.sun.source.util.TreePath;
048: import java.io.IOException;
049: import java.util.Arrays;
050: import java.util.Collections;
051: import java.util.EnumSet;
052: import java.util.HashSet;
053: import java.util.List;
054: import java.util.Set;
055: import javax.lang.model.element.Element;
056: import javax.lang.model.element.Modifier;
057: import org.netbeans.api.java.source.Task;
058: import org.netbeans.api.java.source.CompilationInfo;
059: import org.netbeans.api.java.source.JavaSource;
060: import org.netbeans.api.java.source.JavaSource.Phase;
061: import org.netbeans.api.java.source.TreePathHandle;
062: import org.netbeans.api.java.source.WorkingCopy;
063: import org.netbeans.modules.java.hints.spi.ErrorRule;
064: import org.netbeans.modules.java.hints.spi.ErrorRule.Data;
065: import org.netbeans.spi.editor.hints.ChangeInfo;
066: import org.netbeans.spi.editor.hints.Fix;
067: import org.openide.filesystems.FileObject;
068: import org.openide.util.Exceptions;
069: import org.openide.util.NbBundle;
070:
071: /**
072: *
073: * @author Jan Lahoda
074: */
075: public class MakeVariableFinal implements ErrorRule<Void> {
076:
077: public MakeVariableFinal() {
078: }
079:
080: private static final Set<String> CODES = new HashSet<String>(
081: Arrays
082: .asList("compiler.err.local.var.accessed.from.icls.needs.final"));
083:
084: public Set<String> getCodes() {
085: return CODES;
086: }
087:
088: public List<Fix> run(CompilationInfo compilationInfo,
089: String diagnosticKey, int offset, TreePath treePath,
090: Data<Void> data) {
091: Tree leaf = treePath.getLeaf();
092:
093: if (leaf.getKind() == Kind.IDENTIFIER) {
094: Element el = compilationInfo.getTrees()
095: .getElement(treePath);
096: TreePath declaration = compilationInfo.getTrees().getPath(
097: el);
098:
099: if (declaration != null) {
100: return Collections.singletonList((Fix) new FixImpl(
101: compilationInfo.getFileObject(), el
102: .getSimpleName().toString(),
103: TreePathHandle.create(declaration,
104: compilationInfo)));
105: }
106: }
107:
108: return Collections.<Fix> emptyList();
109: }
110:
111: public void cancel() {
112: }
113:
114: public String getId() {
115: return MakeVariableFinal.class.getName();
116: }
117:
118: public String getDisplayName() {
119: return NbBundle.getMessage(MakeVariableFinal.class,
120: "DN_MakeVariableFinal");
121: }
122:
123: public String getDescription() {
124: return NbBundle.getMessage(MakeVariableFinal.class,
125: "DESC_MakeVariableFinal");
126: }
127:
128: private static final class FixImpl implements Fix {
129:
130: private String variableName;
131: private TreePathHandle variable;
132: private FileObject file;
133:
134: public FixImpl(FileObject file, String variableName,
135: TreePathHandle variable) {
136: this .file = file;
137: this .variableName = variableName;
138: this .variable = variable;
139: }
140:
141: public String getText() {
142: return NbBundle.getMessage(MakeVariableFinal.class,
143: "FIX_MakeVariableFinal", new Object[] { String
144: .valueOf(variableName) });
145: }
146:
147: public ChangeInfo implement() throws IOException {
148: JavaSource js = JavaSource.forFileObject(file);
149:
150: js.runModificationTask(new Task<WorkingCopy>() {
151: public void run(WorkingCopy wc) throws IOException {
152: wc.toPhase(Phase.RESOLVED);
153: TreePath tp = variable.resolve(wc);
154:
155: if (tp == null)
156: return;
157:
158: VariableTree vt = (VariableTree) tp.getLeaf();
159: ModifiersTree mt = vt.getModifiers();
160: Set<Modifier> modifiers = EnumSet
161: .noneOf(Modifier.class);
162:
163: modifiers.addAll(mt.getFlags());
164: modifiers.add(Modifier.FINAL);
165:
166: ModifiersTree newMod = wc.getTreeMaker().Modifiers(
167: modifiers, mt.getAnnotations());
168:
169: wc.rewrite(mt, newMod);
170: }
171: }).commit();
172:
173: return null;
174: }
175: }
176: }
|