1 11 package org.eclipse.jdt.internal.ui.refactoring.nls.search; 12 13 import java.io.BufferedInputStream ; 14 import java.io.ByteArrayInputStream ; 15 import java.io.IOException ; 16 import java.io.InputStream ; 17 import java.util.Enumeration ; 18 import java.util.HashSet ; 19 import java.util.Iterator ; 20 import java.util.Set ; 21 22 import org.eclipse.core.runtime.CoreException; 23 import org.eclipse.core.runtime.IProgressMonitor; 24 25 import org.eclipse.core.filebuffers.FileBuffers; 26 import org.eclipse.core.filebuffers.ITextFileBuffer; 27 import org.eclipse.core.filebuffers.ITextFileBufferManager; 28 import org.eclipse.core.filebuffers.LocationKind; 29 30 import org.eclipse.core.resources.IFile; 31 32 import org.eclipse.jface.text.Position; 33 34 import org.eclipse.search.ui.text.Match; 35 36 import org.eclipse.jdt.core.ICompilationUnit; 37 import org.eclipse.jdt.core.IField; 38 import org.eclipse.jdt.core.IJavaElement; 39 import org.eclipse.jdt.core.ISourceReference; 40 import org.eclipse.jdt.core.ToolFactory; 41 import org.eclipse.jdt.core.compiler.IScanner; 42 import org.eclipse.jdt.core.compiler.ITerminalSymbols; 43 import org.eclipse.jdt.core.compiler.InvalidInputException; 44 import org.eclipse.jdt.core.search.SearchMatch; 45 import org.eclipse.jdt.core.search.SearchRequestor; 46 47 import org.eclipse.jdt.internal.corext.refactoring.nls.PropertyFileDocumentModel; 48 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 49 import org.eclipse.jdt.internal.corext.util.Messages; 50 51 import org.eclipse.jdt.internal.ui.JavaPlugin; 52 import org.eclipse.jdt.internal.ui.util.StringMatcher; 53 54 class NLSSearchResultRequestor extends SearchRequestor { 55 58 59 private static final StringMatcher fgGetClassNameMatcher= new StringMatcher("*.class.getName()*", false, false); 61 private NLSSearchResult fResult; 62 private IFile fPropertiesFile; 63 private Properties fProperties; 64 private HashSet fUsedPropertyNames; 65 66 public NLSSearchResultRequestor(IFile propertiesFile, NLSSearchResult result) { 67 fPropertiesFile= propertiesFile; 68 fResult= result; 69 } 70 71 74 public void beginReporting() { 75 loadProperties(); 76 fUsedPropertyNames= new HashSet (fProperties.size()); 77 } 78 79 82 public void acceptSearchMatch(SearchMatch match) throws CoreException { 83 if (match.getAccuracy() == SearchMatch.A_INACCURATE) 84 return; 85 86 int offset= match.getOffset(); 87 int length= match.getLength(); 88 if (offset == -1 || length == -1) 89 return; 90 91 if (! (match.getElement() instanceof IJavaElement)) 92 return; 93 IJavaElement javaElement= (IJavaElement) match.getElement(); 94 95 if (javaElement.getElementType() == IJavaElement.IMPORT_DECLARATION) 97 return; 98 if (javaElement.getElementType() == IJavaElement.CLASS_FILE) 99 return; if (javaElement.getElementType() == IJavaElement.TYPE) 101 return; 103 if (javaElement.getElementType() == IJavaElement.FIELD) { 105 IField field= (IField) javaElement; 106 String source= field.getSource(); 107 if (source != null && fgGetClassNameMatcher.match(source)) 108 return; 109 } 110 111 if (javaElement instanceof ISourceReference) { 112 String source= ((ISourceReference) javaElement).getSource(); 113 if (source != null) { 114 if (source.indexOf("NLS.initializeMessages") != -1) return; 116 } 117 } 118 119 Position mutableKeyPosition= new Position(offset, length); 121 String key= findKey(mutableKeyPosition, javaElement); 123 if (key != null && isKeyDefined(key)) 124 return; 125 126 ICompilationUnit[] allCompilationUnits= JavaModelUtil.getAllCompilationUnits(new IJavaElement[] {javaElement}); 127 Object element= javaElement; 128 if (allCompilationUnits != null && allCompilationUnits.length == 1) 129 element= allCompilationUnits[0]; 130 131 fResult.addMatch(new Match(element, mutableKeyPosition.getOffset(), mutableKeyPosition.getLength())); 132 } 133 134 public void reportUnusedPropertyNames(IProgressMonitor pm) { 135 pm.beginTask("", fProperties.size()); boolean hasUnused= false; 138 pm.setTaskName(NLSSearchMessages.NLSSearchResultRequestor_searching); 139 String message= Messages.format(NLSSearchMessages.NLSSearchResultCollector_unusedKeys, getPropertiesName(fPropertiesFile)); 140 FileEntry groupElement= new FileEntry(fPropertiesFile, message); 141 142 for (Enumeration enumeration= fProperties.propertyNames(); enumeration.hasMoreElements();) { 143 String propertyName= (String ) enumeration.nextElement(); 144 if (!fUsedPropertyNames.contains(propertyName)) { 145 addMatch(groupElement, propertyName); 146 hasUnused= true; 147 } 148 pm.worked(1); 149 } 150 if (hasUnused) 151 fResult.addFileEntryGroup(groupElement); 152 pm.done(); 153 } 154 155 private String getPropertiesName(IFile propertiesFile) { 156 String path= propertiesFile.getFullPath().removeLastSegments(1).toOSString(); 157 return propertiesFile.getName() + " - " + path; } 159 160 private void addMatch(FileEntry groupElement, String propertyName) { 161 170 String escapedPropertyName= PropertyFileDocumentModel.unwindEscapeChars(propertyName); 171 int start= findPropertyNameStartPosition(escapedPropertyName); 172 int length; 173 if (start == -1) { start= 0; 175 length= 0; 176 } else { 177 length= escapedPropertyName.length(); 178 } 179 fResult.addMatch(new Match(groupElement, start, length)); 180 } 181 182 189 private boolean isKeyDefined(String key) { 190 if (key == null) 191 return true; 193 fUsedPropertyNames.add(key); 194 if (fProperties.getProperty(key) != null) { 195 return true; 196 } 197 return false; 198 } 199 200 public boolean hasPropertyKey(String key) { 201 return fProperties.containsKey(key); 202 } 203 204 public boolean isUsedPropertyKey(String key) { 205 return fUsedPropertyNames.contains(key); 206 } 207 208 217 private String findKey(Position keyPositionResult, IJavaElement enclosingElement) throws CoreException { 218 ICompilationUnit unit= (ICompilationUnit)enclosingElement.getAncestor(IJavaElement.COMPILATION_UNIT); 219 if (unit == null) 220 return null; 221 222 String source= unit.getSource(); 223 if (source == null) 224 return null; 225 226 IScanner scanner= ToolFactory.createScanner(false, false, false, false); 227 scanner.setSource(source.toCharArray()); 228 scanner.resetTo(keyPositionResult.getOffset() + keyPositionResult.getLength(), source.length()); 229 230 try { 231 if (scanner.getNextToken() != ITerminalSymbols.TokenNameDOT) 232 return null; 233 234 if (scanner.getNextToken() != ITerminalSymbols.TokenNameIdentifier) 235 return null; 236 237 String SRC= new String (scanner.getCurrentTokenSource()); 238 int keyStart= scanner.getCurrentTokenStartPosition(); 239 int keyEnd= scanner.getCurrentTokenEndPosition(); 240 241 if (scanner.getNextToken() == ITerminalSymbols.TokenNameLPAREN) { 242 if (scanner.getNextToken() != ITerminalSymbols.TokenNameStringLiteral) 245 return null; 246 keyStart= scanner.getCurrentTokenStartPosition() + 1; 248 keyEnd= scanner.getCurrentTokenEndPosition(); 249 keyPositionResult.setOffset(keyStart); 250 keyPositionResult.setLength(keyEnd - keyStart); 251 return source.substring(keyStart, keyEnd); 252 } else { 253 keyPositionResult.setOffset(keyStart); 254 keyPositionResult.setLength(keyEnd - keyStart + 1); 255 return src; 256 } 257 } catch (InvalidInputException e) { 258 return null; 259 } 260 } 261 262 269 private int findPropertyNameStartPosition(String propertyName) { 270 InputStream stream= null; 272 LineReader lineReader= null; 273 String encoding; 274 try { 275 encoding= fPropertiesFile.getCharset(); 276 } catch (CoreException e1) { 277 encoding= "ISO-8859-1"; } 279 try { 280 stream= createInputStream(fPropertiesFile); 281 lineReader= new LineReader(stream, encoding); 282 } catch (CoreException cex) { 283 JavaPlugin.log(cex); 285 return -1; 286 } catch (IOException e) { 287 if (stream != null) { 288 try { 289 stream.close(); 290 } catch (IOException ce) { 291 JavaPlugin.log(ce); 292 } 293 } 294 return -1; 295 } 296 int start= 0; 297 try { 298 StringBuffer buf= new StringBuffer (80); 299 int eols= lineReader.readLine(buf); 300 int keyLength= propertyName.length(); 301 while (eols > 0) { 302 String line= buf.toString(); 303 int i= line.indexOf(propertyName); 304 int charPos= i + keyLength; 305 char terminatorChar= 0; 306 boolean hasNoValue= (charPos >= line.length()); 307 if (i > -1 && !hasNoValue) 308 terminatorChar= line.charAt(charPos); 309 if (line.trim().startsWith(propertyName) && 310 (hasNoValue || Character.isWhitespace(terminatorChar) || terminatorChar == '=')) { 311 start += line.indexOf(propertyName); 312 eols= -17; } else { 314 start += line.length() + eols; 315 buf.setLength(0); 316 eols= lineReader.readLine(buf); 317 } 318 } 319 if (eols != -17) 320 start= -1; } catch (IOException ex) { 322 JavaPlugin.log(ex); 323 return -1; 324 } finally { 325 try { 326 lineReader.close(); 327 } catch (IOException ex) { 328 JavaPlugin.log(ex); 329 } 330 } 331 return start; 332 } 333 334 private void loadProperties() { 335 Set duplicateKeys= new HashSet (); 336 fProperties= new Properties(duplicateKeys); 337 InputStream stream; 338 try { 339 stream= new BufferedInputStream (createInputStream(fPropertiesFile)); 340 } catch (CoreException ex) { 341 fProperties= new Properties(); 342 return; 343 } 344 try { 345 fProperties.load(stream); 346 } catch (IOException ex) { 347 fProperties= new Properties(); 348 return; 349 } finally { 350 try { 351 stream.close(); 352 } catch (IOException ex) { 353 } 354 reportDuplicateKeys(duplicateKeys); 355 } 356 } 357 358 private InputStream createInputStream(IFile propertiesFile) throws CoreException { 359 ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager(); 360 if (manager != null) { 361 ITextFileBuffer buffer= manager.getTextFileBuffer(propertiesFile.getFullPath(), LocationKind.IFILE); 362 if (buffer != null) { 363 return new ByteArrayInputStream (buffer.getDocument().get().getBytes()); 364 } 365 } 366 367 return propertiesFile.getContents(); 368 } 369 370 private void reportDuplicateKeys(Set duplicateKeys) { 371 if (duplicateKeys.size() == 0) 372 return; 373 374 String message= Messages.format(NLSSearchMessages.NLSSearchResultCollector_duplicateKeys, getPropertiesName(fPropertiesFile)); 375 FileEntry groupElement= new FileEntry(fPropertiesFile, message); 376 Iterator iter= duplicateKeys.iterator(); 377 while (iter.hasNext()) { 378 String propertyName= (String ) iter.next(); 379 addMatch(groupElement, propertyName); 380 } 381 fResult.addFileEntryGroup(groupElement); 382 } 383 384 } 385 | Popular Tags |