2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * created at Jan 7, 2002
21 package com
.intellij
.compiler
.make
;
23 import com
.intellij
.compiler
.SymbolTable
;
24 import com
.intellij
.compiler
.classParsing
.*;
25 import com
.intellij
.compiler
.impl
.CompilerUtil
;
26 import com
.intellij
.compiler
.impl
.javaCompiler
.DependencyProcessor
;
27 import com
.intellij
.openapi
.application
.ApplicationManager
;
28 import com
.intellij
.openapi
.compiler
.CompileContext
;
29 import com
.intellij
.openapi
.diagnostic
.Logger
;
30 import com
.intellij
.openapi
.progress
.ProcessCanceledException
;
31 import com
.intellij
.openapi
.project
.Project
;
32 import com
.intellij
.openapi
.util
.Computable
;
33 import com
.intellij
.openapi
.util
.Pair
;
34 import com
.intellij
.openapi
.vfs
.VirtualFile
;
35 import com
.intellij
.util
.ArrayUtil
;
36 import com
.intellij
.util
.cls
.ClsFormatException
;
37 import com
.intellij
.util
.cls
.ClsUtil
;
38 import gnu
.trove
.TIntHashSet
;
39 import org
.jetbrains
.annotations
.NonNls
;
40 import org
.jetbrains
.annotations
.NotNull
;
41 import org
.jetbrains
.annotations
.Nullable
;
44 import java
.io
.IOException
;
45 import java
.rmi
.Remote
;
48 public class DependencyCache
{
49 private static final Logger LOG
= Logger
.getInstance("#com.intellij.compiler.make.DependencyCache");
51 private Cache myCache
;
52 private Cache myNewClassesCache
;
54 private static final String REMOTE_INTERFACE_NAME
= Remote
.class.getName();
55 private TIntHashSet myToUpdate
= new TIntHashSet(); // qName strings to be updated.
56 private final TIntHashSet myTraverseRoots
= new TIntHashSet(); // Dependencies are calculated from these clasess
57 private final TIntHashSet myClassesWithSourceRemoved
= new TIntHashSet();
58 private final TIntHashSet myPreviouslyRemoteClasses
= new TIntHashSet(); // classes that were Remote, but became non-Remote for some reason
59 private final TIntHashSet myMarkedInfos
= new TIntHashSet(); // classes to be recompiled
60 private final Set
<VirtualFile
> myMarkedFiles
= new HashSet
<VirtualFile
>();
62 private DependencyCacheNavigator myCacheNavigator
;
63 private SymbolTable mySymbolTable
;
64 private final String mySymbolTableFilePath
;
65 private final String myStoreDirectoryPath
;
66 @NonNls private static final String SYMBOLTABLE_FILE_NAME
= "symboltable.dat";
68 public DependencyCache(@NonNls String storeDirectoryPath
) {
69 myStoreDirectoryPath
= storeDirectoryPath
;
70 LOG
.assertTrue(myStoreDirectoryPath
!= null);
72 mySymbolTableFilePath
= myStoreDirectoryPath
+ "/" + SYMBOLTABLE_FILE_NAME
;
75 public DependencyCacheNavigator
getCacheNavigator() throws CacheCorruptedException
{
76 if (myCacheNavigator
== null) {
77 myCacheNavigator
= new DependencyCacheNavigator(getCache());
79 return myCacheNavigator
;
82 public void wipe() throws CacheCorruptedException
{
84 getNewClassesCache().wipe();
87 public Cache
getCache() throws CacheCorruptedException
{
89 if (myCache
== null) {
90 // base number of cached record views of each type
91 myCache
= new Cache(myStoreDirectoryPath
, 512);
96 catch (IOException e
) {
97 throw new CacheCorruptedException(e
);
101 public Cache
getNewClassesCache() throws CacheCorruptedException
{
103 if (myNewClassesCache
== null) {
104 myNewClassesCache
= new Cache(myStoreDirectoryPath
+ "/tmp", 16);
106 return myNewClassesCache
;
108 catch (IOException e
) {
109 throw new CacheCorruptedException(e
);
113 public void addTraverseRoot(int qName
) {
114 myTraverseRoots
.add(qName
);
117 public void clearTraverseRoots() {
118 myTraverseRoots
.clear();
121 public boolean hasUnprocessedTraverseRoots() {
122 return !myTraverseRoots
.isEmpty();
125 public void markSourceRemoved(int qName
) {
126 myClassesWithSourceRemoved
.add(qName
);
129 public void addClassToUpdate(int qName
) {
130 myToUpdate
.add(qName
);
133 public int reparseClassFile(@NotNull File file
, final byte[] fileContent
) throws ClsFormatException
, CacheCorruptedException
{
134 SymbolTable symbolTable
= getSymbolTable();
136 final int qName
= getNewClassesCache().importClassInfo(new ClassFileReader(file
, symbolTable
, fileContent
), symbolTable
);
137 addClassToUpdate(qName
);
138 addTraverseRoot(qName
);
142 // for profiling purposes
144 private static void pause() {
145 System.out.println("PAUSED. ENTER A CHAR.");
146 byte[] buf = new byte[1];
150 catch (IOException e) {
156 public void update() throws CacheCorruptedException
{
157 if (myToUpdate
.isEmpty()) {
158 return; // optimization
161 final long updateStart
= System
.currentTimeMillis();
164 final int[] namesToUpdate
= myToUpdate
.toArray();
165 final Cache cache
= getCache();
166 final Cache newCache
= getNewClassesCache();
167 final DependencyCacheNavigator navigator
= getCacheNavigator();
169 // remove unnecesary dependencies
170 for (final int qName
: namesToUpdate
) {
171 // process use-dependencies
172 for (int referencedClassQName
: cache
.getReferencedClasses(qName
)) {
173 if (!cache
.containsClass(referencedClassQName
)) {
176 cache
.removeClassReferencer(referencedClassQName
, qName
);
178 cache
.clearReferencedClasses(qName
);
179 // process inheritance dependencies
180 navigator
.walkSuperClasses(qName
, new ClassInfoProcessor() {
181 public boolean process(int classQName
) throws CacheCorruptedException
{
182 cache
.removeSubclass(classQName
, qName
);
188 // do update of classInfos
189 for (final int qName
: namesToUpdate
) {
190 cache
.importClassInfo(newCache
, qName
);
193 // build forward-dependencies for the new infos, all new class infos must be already in the main cache!
195 final SymbolTable symbolTable
= getSymbolTable();
197 for (final int qName
: namesToUpdate
) {
198 if (!newCache
.containsClass(qName
)) {
201 buildForwardDependencies(qName
, newCache
.getReferences(qName
));
202 boolean isRemote
= false;
203 // "remote objects" are classes that _directly_ implement remote interfaces
204 final int[] superInterfaces
= cache
.getSuperInterfaces(qName
);
205 if (superInterfaces
.length
> 0) {
206 final int remoteInterfaceName
= symbolTable
.getId(REMOTE_INTERFACE_NAME
);
207 for (int superInterface
: superInterfaces
) {
208 if (isRemoteInterface(cache
, superInterface
, remoteInterfaceName
)) {
214 final boolean wasRemote
= cache
.isRemote(qName
);
215 if (wasRemote
&& !isRemote
) {
216 synchronized (myPreviouslyRemoteClasses
) {
217 myPreviouslyRemoteClasses
.add(qName
);
220 cache
.setRemote(qName
, isRemote
);
223 // building subclass dependencies
224 for (final int qName
: namesToUpdate
) {
225 buildSubclassDependencies(getCache(), qName
, qName
);
228 for (final int qName
: myClassesWithSourceRemoved
.toArray()) {
229 cache
.removeClass(qName
);
231 myToUpdate
= new TIntHashSet();
233 CompilerUtil
.logDuration("Dependency cache update", System
.currentTimeMillis() - updateStart
);
237 private void buildForwardDependencies(final int classQName
, final Collection
<ReferenceInfo
> references
) throws CacheCorruptedException
{
238 final Cache cache
= getCache();
240 final int genericSignature
= cache
.getGenericSignature(classQName
);
241 if (genericSignature
!= -1) {
242 final String genericClassSignature
= resolve(genericSignature
);
243 final int[] bounds
= findBounds(genericClassSignature
);
244 for (int boundClassQName
: bounds
) {
245 cache
.addClassReferencer(boundClassQName
, classQName
);
249 buildAnnotationDependencies(classQName
, cache
.getRuntimeVisibleAnnotations(classQName
));
250 buildAnnotationDependencies(classQName
, cache
.getRuntimeInvisibleAnnotations(classQName
));
252 for (final ReferenceInfo refInfo
: references
) {
253 final int declaringClassName
= getActualDeclaringClassForReference(refInfo
);
254 if (declaringClassName
== Cache
.UNKNOWN
) {
257 if (refInfo
instanceof MemberReferenceInfo
) {
258 final MemberInfo memberInfo
= ((MemberReferenceInfo
)refInfo
).getMemberInfo();
259 if (memberInfo
instanceof FieldInfo
) {
260 cache
.addFieldReferencer(declaringClassName
, memberInfo
.getName(), classQName
);
262 else if (memberInfo
instanceof MethodInfo
) {
263 cache
.addMethodReferencer(declaringClassName
, memberInfo
.getName(), memberInfo
.getDescriptor(), classQName
);
266 LOG
.error("Unknown member info class: " + memberInfo
.getClass().getName());
269 else { // reference to class
270 cache
.addClassReferencer(declaringClassName
, classQName
);
273 final SymbolTable symbolTable
= getSymbolTable();
275 for (final FieldInfo fieldInfo
: cache
.getFields(classQName
)) {
276 buildAnnotationDependencies(classQName
, fieldInfo
.getRuntimeVisibleAnnotations());
277 buildAnnotationDependencies(classQName
, fieldInfo
.getRuntimeInvisibleAnnotations());
279 String className
= MakeUtil
.parseObjectType(symbolTable
.getSymbol(fieldInfo
.getDescriptor()), 0);
280 if (className
== null) {
283 final int cls
= symbolTable
.getId(className
);
284 cache
.addClassReferencer(cls
, classQName
);
287 for (final MethodInfo methodInfo
: cache
.getMethods(classQName
)) {
288 buildAnnotationDependencies(classQName
, methodInfo
.getRuntimeVisibleAnnotations());
289 buildAnnotationDependencies(classQName
, methodInfo
.getRuntimeInvisibleAnnotations());
290 buildAnnotationDependencies(classQName
, methodInfo
.getRuntimeVisibleParameterAnnotations());
291 buildAnnotationDependencies(classQName
, methodInfo
.getRuntimeInvisibleParameterAnnotations());
293 if (methodInfo
.isConstructor()) {
297 final String returnTypeClassName
= MakeUtil
.parseObjectType(methodInfo
.getReturnTypeDescriptor(symbolTable
), 0);
298 if (returnTypeClassName
!= null) {
299 final int returnTypeClassQName
= symbolTable
.getId(returnTypeClassName
);
300 cache
.addClassReferencer(returnTypeClassQName
, classQName
);
303 String
[] parameterSignatures
= CacheUtils
.getParameterSignatures(methodInfo
, symbolTable
);
304 for (String parameterSignature
: parameterSignatures
) {
305 String paramClassName
= MakeUtil
.parseObjectType(parameterSignature
, 0);
306 if (paramClassName
!= null) {
307 final int paramClassId
= symbolTable
.getId(paramClassName
);
308 cache
.addClassReferencer(paramClassId
, classQName
);
314 private static boolean isRemoteInterface(Cache cache
, int ifaceName
, final int remoteInterfaceName
) throws CacheCorruptedException
{
315 if (ifaceName
== remoteInterfaceName
) {
318 for (int superInterfaceName
: cache
.getSuperInterfaces(ifaceName
)) {
319 if (isRemoteInterface(cache
, superInterfaceName
, remoteInterfaceName
)) {
327 private void buildAnnotationDependencies(int classQName
, AnnotationConstantValue
[][] annotations
) throws CacheCorruptedException
{
328 if (annotations
== null || annotations
.length
== 0) {
331 for (AnnotationConstantValue
[] annotation
: annotations
) {
332 buildAnnotationDependencies(classQName
, annotation
);
336 private void buildAnnotationDependencies(int classQName
, AnnotationConstantValue
[] annotations
) throws CacheCorruptedException
{
337 if (annotations
== null || annotations
.length
== 0) {
340 final Cache cache
= getCache();
341 for (AnnotationConstantValue annotation
: annotations
) {
342 final int annotationQName
= annotation
.getAnnotationQName();
344 cache
.addClassReferencer(annotationQName
, classQName
);
346 final AnnotationNameValuePair
[] memberValues
= annotation
.getMemberValues();
347 for (final AnnotationNameValuePair nameValuePair
: memberValues
) {
348 for (MethodInfo annotationMember
: cache
.findMethodsByName(annotationQName
, nameValuePair
.getName())) {
349 cache
.addMethodReferencer(annotationQName
, annotationMember
.getName(), annotationMember
.getDescriptor(), classQName
);
355 private int[] findBounds(final String genericClassSignature
) throws CacheCorruptedException
{
357 final String
[] boundInterfaces
= BoundsParser
.getBounds(genericClassSignature
);
358 int[] ids
= ArrayUtil
.newIntArray(boundInterfaces
.length
);
359 for (int i
= 0; i
< boundInterfaces
.length
; i
++) {
360 ids
[i
] = getSymbolTable().getId(boundInterfaces
[i
]);
364 catch (SignatureParsingException e
) {
365 return ArrayUtil
.EMPTY_INT_ARRAY
;
369 // fixes JDK 1.4 javac bug that generates references in the constant pool
370 // to the subclass even if the field was declared in a superclass
371 private int getActualDeclaringClassForReference(final ReferenceInfo refInfo
) throws CacheCorruptedException
{
372 if (!(refInfo
instanceof MemberReferenceInfo
)) {
373 return refInfo
.getClassName();
375 final int declaringClassName
= refInfo
.getClassName();
376 final Cache cache
= getCache();
377 final MemberInfo memberInfo
= ((MemberReferenceInfo
)refInfo
).getMemberInfo();
378 if (memberInfo
instanceof FieldInfo
) {
379 if (cache
.findFieldByName(declaringClassName
, memberInfo
.getName()) != null) {
380 return declaringClassName
;
383 else if (memberInfo
instanceof MethodInfo
) {
384 if (cache
.findMethod(declaringClassName
, memberInfo
.getName(), memberInfo
.getDescriptor()) != null) {
385 return declaringClassName
;
388 final DeclaringClassFinder finder
= new DeclaringClassFinder(memberInfo
);
389 getCacheNavigator().walkSuperClasses(declaringClassName
, finder
);
390 return finder
.getDeclaringClassName();
394 * @return qualified names of the classes that should be additionally recompiled
396 public Pair
<int[], Set
<VirtualFile
>> findDependentClasses(CompileContext context
, Project project
, Set
<VirtualFile
> successfullyCompiled
, @Nullable final DependencyProcessor additionalProcessor
)
397 throws CacheCorruptedException
{
399 markDependencies(context
, project
, successfullyCompiled
, additionalProcessor
);
400 return new Pair
<int[], Set
<VirtualFile
>>(myMarkedInfos
.toArray(), Collections
.unmodifiableSet(myMarkedFiles
));
403 private void markDependencies(CompileContext context
, Project project
, final Set
<VirtualFile
> successfullyCompiled
,
404 @Nullable final DependencyProcessor additionalProcessor
) throws CacheCorruptedException
{
406 if (LOG
.isDebugEnabled()) {
407 LOG
.debug("====================Marking dependent files=====================");
409 // myToUpdate can be modified during the mark procedure, so use toArray() to iterate it
410 final int[] traverseRoots
= myTraverseRoots
.toArray();
411 final SourceFileFinder sourceFileFinder
= new SourceFileFinder(project
, context
);
412 final CachingSearcher searcher
= new CachingSearcher(project
);
413 final ChangedRetentionPolicyDependencyProcessor changedRetentionPolicyDependencyProcessor
= new ChangedRetentionPolicyDependencyProcessor(project
, searcher
, this);
414 for (final int qName
: traverseRoots
) {
415 if (!getCache().containsClass(qName
)) {
418 if (getNewClassesCache().containsClass(qName
)) { // there is a new class file created
419 new JavaDependencyProcessor(project
, this, qName
).run();
420 ArrayList
<ChangedConstantsDependencyProcessor
.FieldChangeInfo
> changed
=
421 new ArrayList
<ChangedConstantsDependencyProcessor
.FieldChangeInfo
>();
422 ArrayList
<ChangedConstantsDependencyProcessor
.FieldChangeInfo
> removed
=
423 new ArrayList
<ChangedConstantsDependencyProcessor
.FieldChangeInfo
>();
424 findModifiedConstants(qName
, changed
, removed
);
425 if (!changed
.isEmpty() || !removed
.isEmpty()) {
426 new ChangedConstantsDependencyProcessor(
427 project
, searcher
, this, qName
,
428 changed
.toArray(new ChangedConstantsDependencyProcessor
.FieldChangeInfo
[changed
.size()]),
429 removed
.toArray(new ChangedConstantsDependencyProcessor
.FieldChangeInfo
[removed
.size()])
432 changedRetentionPolicyDependencyProcessor
.checkAnnotationRetentionPolicyChanges(qName
);
433 if (additionalProcessor
!= null) {
434 additionalProcessor
.processDependencies(context
, qName
);
438 boolean isSourceDeleted
= false;
439 if (myClassesWithSourceRemoved
.contains(qName
)) { // no recompiled class file, check whether the classfile exists
440 isSourceDeleted
= true;
442 else if (!new File(getCache().getPath(qName
)).exists()) {
443 final String qualifiedName
= resolve(qName
);
444 final String sourceFileName
= getCache().getSourceFileName(qName
);
445 final boolean markAsRemovedSource
= ApplicationManager
.getApplication().runReadAction(new Computable
<Boolean
>() {
446 public Boolean
compute() {
447 VirtualFile sourceFile
= sourceFileFinder
.findSourceFile(qualifiedName
, sourceFileName
);
448 return sourceFile
== null || successfullyCompiled
.contains(sourceFile
) ? Boolean
.TRUE
: Boolean
.FALSE
;
451 if (markAsRemovedSource
) {
452 // for Inner classes: sourceFile may exist, but the inner class declaration inside it may not,
453 // thus the source for the class info should be considered removed
454 isSourceDeleted
= true;
455 markSourceRemoved(qName
);
456 myMarkedInfos
.remove(qName
); // if the info has been marked already, the mark should be removed
459 if (isSourceDeleted
) {
460 Dependency
[] backDependencies
= getCache().getBackDependencies(qName
);
461 for (Dependency backDependency
: backDependencies
) {
462 if (markTargetClassInfo(backDependency
)) {
463 if (LOG
.isDebugEnabled()) {
465 "Mark dependent class " + backDependency
.getClassQualifiedName() + "; reason: no class file found for " + qName
);
472 if (LOG
.isDebugEnabled()) {
473 LOG
.debug("================================================================");
476 catch (ProcessCanceledException ignored
) {
477 // deliberately suppressed
481 private void findModifiedConstants(
483 Collection
<ChangedConstantsDependencyProcessor
.FieldChangeInfo
> changedConstants
,
484 Collection
<ChangedConstantsDependencyProcessor
.FieldChangeInfo
> removedConstants
) throws CacheCorruptedException
{
486 final Cache cache
= getCache();
487 for (final FieldInfo field
: cache
.getFields(qName
)) {
488 final int oldFlags
= field
.getFlags();
489 if (ClsUtil
.isStatic(oldFlags
) && ClsUtil
.isFinal(oldFlags
)) {
490 final Cache newClassesCache
= getNewClassesCache();
491 FieldInfo newField
= newClassesCache
.findFieldByName(qName
, field
.getName());
492 if (newField
== null) {
493 if (!ConstantValue
.EMPTY_CONSTANT_VALUE
.equals(field
.getConstantValue())) {
494 // if the field was really compile time constant
495 removedConstants
.add(new ChangedConstantsDependencyProcessor
.FieldChangeInfo(field
));
499 final boolean visibilityRestricted
= MakeUtil
.isMoreAccessible(oldFlags
, newField
.getFlags());
500 if (!field
.getConstantValue().equals(newField
.getConstantValue()) || visibilityRestricted
) {
501 changedConstants
.add(new ChangedConstantsDependencyProcessor
.FieldChangeInfo(field
, visibilityRestricted
));
508 private static void buildSubclassDependencies(Cache cache
, final int qName
, int targetClassId
) throws CacheCorruptedException
{
509 final int superQName
= cache
.getSuperQualifiedName(targetClassId
);
510 if (superQName
!= Cache
.UNKNOWN
) {
511 cache
.addSubclass(superQName
, qName
);
512 buildSubclassDependencies(cache
, qName
, superQName
);
515 int[] interfaces
= cache
.getSuperInterfaces(targetClassId
);
516 for (final int interfaceName
: interfaces
) {
517 cache
.addSubclass(interfaceName
, qName
);
518 buildSubclassDependencies(cache
, qName
, interfaceName
);
524 * Marks ClassInfo targeted by the dependency
525 * @return true if really added, false otherwise
527 public boolean markTargetClassInfo(Dependency dependency
) throws CacheCorruptedException
{
528 return markClassInfo(dependency
.getClassQualifiedName(), false);
532 * Marks ClassInfo that corresponds to the specified qualified name
533 * If class info is already recompiled, it is not marked
534 * @return true if really added, false otherwise
536 public boolean markClass(int qualifiedName
) throws CacheCorruptedException
{
537 return markClass(qualifiedName
, false);
541 * Marks ClassInfo that corresponds to the specified qualified name
542 * If class info is already recompiled, it is not marked unless force parameter is true
543 * @return true if really added, false otherwise
545 public boolean markClass(int qualifiedName
, boolean force
) throws CacheCorruptedException
{
546 return markClassInfo(qualifiedName
, force
);
549 public boolean isTargetClassInfoMarked(Dependency dependency
) {
550 return isClassInfoMarked(dependency
.getClassQualifiedName());
553 public boolean isClassInfoMarked(int qName
) {
554 return myMarkedInfos
.contains(qName
);
557 public void markFile(VirtualFile file
) {
558 myMarkedFiles
.add(file
);
562 * @return true if really marked, false otherwise
564 private boolean markClassInfo(int qName
, boolean force
) throws CacheCorruptedException
{
565 if (!getCache().containsClass(qName
)) {
568 if (myClassesWithSourceRemoved
.contains(qName
)) {
569 return false; // no need to recompile since source has been removed
572 if (getNewClassesCache().containsClass(qName
)) { // already recompiled
576 return myMarkedInfos
.add(qName
);
579 public void resetState() {
580 final long start
= System
.currentTimeMillis();
583 myClassesWithSourceRemoved
.clear();
584 myMarkedFiles
.clear();
585 myMarkedInfos
.clear();
587 myTraverseRoots
.clear();
588 if (myNewClassesCache
!= null) {
589 myNewClassesCache
.wipe();
590 myNewClassesCache
= null;
592 myCacheNavigator
= null;
594 if (myCache
!= null) {
599 catch (CacheCorruptedException e
) {
603 if (mySymbolTable
!= null) {
604 mySymbolTable
.dispose();
605 mySymbolTable
= null;
608 catch (CacheCorruptedException e
) {
613 CompilerUtil
.logDuration("Dependency cache disposal", System
.currentTimeMillis() - start
);
618 public SymbolTable
getSymbolTable() throws CacheCorruptedException
{
619 if (mySymbolTable
== null) {
620 mySymbolTable
= new SymbolTable(new File(mySymbolTableFilePath
));
622 return mySymbolTable
;
625 public String
resolve(int id
) throws CacheCorruptedException
{
626 return getSymbolTable().getSymbol(id
);
629 public boolean wasRemote(int qName
) {
630 return myPreviouslyRemoteClasses
.contains(qName
);
633 private class DeclaringClassFinder
implements ClassInfoProcessor
{
634 private final int myMemberName
;
635 private final int myMemberDescriptor
;
636 private int myDeclaringClass
= Cache
.UNKNOWN
;
637 private final boolean myIsField
;
639 private DeclaringClassFinder(MemberInfo memberInfo
) {
640 myMemberName
= memberInfo
.getName();
641 myMemberDescriptor
= memberInfo
.getDescriptor();
642 myIsField
= memberInfo
instanceof FieldInfo
;
645 public int getDeclaringClassName() {
646 return myDeclaringClass
;
649 public boolean process(int classQName
) throws CacheCorruptedException
{
650 final Cache cache
= getCache();
652 final FieldInfo fieldId
= cache
.findField(classQName
, myMemberName
, myMemberDescriptor
);
653 if (fieldId
!= null) {
654 myDeclaringClass
= classQName
;
659 final MethodInfo methodId
= cache
.findMethod(classQName
, myMemberName
, myMemberDescriptor
);
660 if (methodId
!= null) {
661 myDeclaringClass
= classQName
;