1 19 20 package org.netbeans.api.java.source; 21 22 import com.sun.source.tree.Tree; 23 import com.sun.source.util.TreePath; 24 import com.sun.tools.javac.tree.JCTree; 25 import java.net.MalformedURLException ; 26 import java.util.ArrayList ; 27 import java.util.logging.Logger ; 28 import javax.lang.model.element.Element; 29 import javax.swing.text.Position.Bias; 30 import org.openide.filesystems.FileObject; 31 import org.openide.filesystems.FileUtil; 32 import org.openide.filesystems.URLMapper; 33 import org.openide.loaders.DataObject; 34 import org.openide.loaders.DataObjectNotFoundException; 35 import org.openide.text.CloneableEditorSupport; 36 import org.openide.text.PositionRef; 37 38 73 public final class TreePathHandle { 74 75 private PositionRef position; 76 private KindPath kindPath; 77 private FileObject file; 78 private ElementHandle enclosingElement; 79 private boolean enclElIsCorrespondingEl; 80 81 85 public FileObject getFileObject() { 86 return file; 87 } 88 89 97 public TreePath resolve (final CompilationInfo compilationInfo) throws IllegalArgumentException { 98 assert compilationInfo != null; 99 if (!compilationInfo.getFileObject().equals(getFileObject())) { 100 throw new IllegalArgumentException ("TreePathHandle ["+FileUtil.getFileDisplayName(getFileObject())+"] was not created from " + FileUtil.getFileDisplayName(compilationInfo.getFileObject())); 101 } 102 Element element = enclosingElement.resolve(compilationInfo); 103 TreePath tp = null; 104 if (element != null) { 105 TreePath startPath = compilationInfo.getTrees().getPath(element); 106 if (startPath == null) { 107 Logger.getLogger(TreePathHandle.class.getName()).fine("compilationInfo.getTrees().getPath(element) returned null for element %s " + element + "(" +file.getPath() +")"); } else { 109 tp = compilationInfo.getTreeUtilities().pathFor(startPath, position.getOffset()+1); 110 } 111 } 112 if (tp == null) { 113 tp = compilationInfo.getTreeUtilities().pathFor(position.getOffset()+1); 114 } 115 if (new KindPath(tp).equals(kindPath)) 116 return tp; 117 else 118 return null; 119 } 120 121 127 public Element resolveElement(final CompilationInfo info) { 128 TreePath tp = null; 129 IllegalStateException ise = null; 130 try { 131 if (info.getFileObject().equals(this.file)) { 132 tp = this.resolve(info); 133 } 134 } catch (IllegalStateException i) { 135 ise=i; 136 } 137 if (tp==null) { 138 if (enclElIsCorrespondingEl) { 139 return enclosingElement.resolve(info); 140 } else { 141 if (ise==null) 142 return null; 143 throw ise; 144 } 145 } 146 Element el = info.getTrees().getElement(tp); 147 if (el==null) { 148 Logger.getLogger(TreePathHandle.class.toString()).fine("info.getTrees().getElement(tp) returned null for " + tp); 149 if (enclElIsCorrespondingEl) { 150 return enclosingElement.resolve(info); 151 } else { 152 return null; 153 } 154 } else { 155 return el; 156 } 157 } 158 159 166 public Tree.Kind getKind() { 167 return kindPath.kindPath.get(0); 168 } 169 170 private TreePathHandle(PositionRef position, KindPath kindPath, FileObject file, ElementHandle element, boolean enclElIsCorrespondingEl) { 171 this.kindPath = kindPath; 172 this.position = position; 173 this.file = file; 174 this.enclosingElement = element; 175 this.enclElIsCorrespondingEl = enclElIsCorrespondingEl; 176 } 177 178 186 public static TreePathHandle create (final TreePath treePath, CompilationInfo info) throws IllegalArgumentException { 187 FileObject file; 188 try { 189 file = URLMapper.findFileObject(treePath.getCompilationUnit().getSourceFile().toUri().toURL()); 190 } catch (MalformedURLException e) { 191 throw (RuntimeException ) new RuntimeException ().initCause(e); 192 } 193 int position = ((JCTree) treePath.getLeaf()).pos; 194 CloneableEditorSupport s = findCloneableEditorSupport(file); 195 PositionRef pos = s.createPositionRef(position, Bias.Forward); 196 TreePath current = treePath; 197 Element element; 198 boolean enclElIsCorrespondingEl = true; 199 do { 200 element = info.getTrees().getElement(current); 201 current = current.getParentPath(); 202 if (element!=null && !isSupported(element)) { 203 enclElIsCorrespondingEl=false; 204 } 205 } while ((element == null || !isSupported(element)) && current !=null); 206 return new TreePathHandle(pos, new KindPath(treePath), file,ElementHandle.create(element), enclElIsCorrespondingEl); 207 } 208 209 private static boolean isSupported(Element el) { 210 switch (el.getKind()) { 211 case PACKAGE: 212 case CLASS: 213 case INTERFACE: 214 case ENUM: 215 case METHOD: 216 case CONSTRUCTOR: 217 case INSTANCE_INIT: 218 case STATIC_INIT: 219 case FIELD: 220 case ANNOTATION_TYPE: 221 case ENUM_CONSTANT: return true; 222 default: return false; 223 } 224 } 225 226 private static CloneableEditorSupport findCloneableEditorSupport(FileObject file) { 227 try { 228 DataObject dob = DataObject.find(file); 229 Object obj = dob.getCookie(org.openide.cookies.OpenCookie.class); 230 if (obj instanceof CloneableEditorSupport) { 231 return (CloneableEditorSupport)obj; 232 } 233 obj = dob.getCookie(org.openide.cookies.EditorCookie.class); 234 if (obj instanceof CloneableEditorSupport) { 235 return (CloneableEditorSupport)obj; 236 } 237 } catch (DataObjectNotFoundException ex) { 238 ex.printStackTrace(); 239 } 240 return null; 241 } 242 243 private static class KindPath { 244 private ArrayList <Tree.Kind> kindPath = new ArrayList (); 245 246 private KindPath(TreePath treePath) { 247 while (treePath!=null) { 248 kindPath.add(treePath.getLeaf().getKind()); 249 treePath = treePath.getParentPath(); 250 } 251 } 252 253 public int hashCode() { 254 return kindPath.hashCode(); 255 } 256 257 public boolean equals(Object object) { 258 if (object instanceof KindPath) 259 return kindPath.equals(((KindPath)object).kindPath); 260 return false; 261 } 262 } 263 } 264 | Popular Tags |