com.android.tools.lint.detector.api.Scope Java Examples

The following examples show how to use com.android.tools.lint.detector.api.Scope. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: IssueRegistry.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
/**
 * Returns all available issues of a given scope (regardless of whether
 * they are actually enabled for a given configuration etc)
 *
 * @param scope the applicable scope set
 * @return a list of issues
 */
@NonNull
protected List<Issue> getIssuesForScope(@NonNull EnumSet<Scope> scope) {
    List<Issue> list = sScopeIssues.get(scope);
    if (list == null) {
        List<Issue> issues = getIssues();
        if (scope.equals(Scope.ALL)) {
            list = issues;
        } else {
            list = new ArrayList<Issue>(getIssueCapacity(scope));
            for (Issue issue : issues) {
                // Determine if the scope matches
                if (issue.getImplementation().isAdequate(scope)) {
                    list.add(issue);
                }
            }
        }
        sScopeIssues.put(scope, list);
    }

    return list;
}
 
Example #2
Source File: BuiltinIssueRegistry.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
@Override
protected int getIssueCapacity(@NonNull EnumSet<Scope> scope) {
    if (scope.equals(Scope.ALL)) {
        return getIssues().size();
    } else {
        int initialSize = 12;
        if (scope.contains(Scope.RESOURCE_FILE)) {
            initialSize += 75;
        } else if (scope.contains(Scope.ALL_RESOURCE_FILES)) {
            initialSize += 10;
        }

        if (scope.contains(Scope.JAVA_FILE)) {
            initialSize += 55;
        } else if (scope.contains(Scope.CLASS_FILE)) {
            initialSize += 15;
        } else if (scope.contains(Scope.MANIFEST)) {
            initialSize += 30;
        } else if (scope.contains(Scope.GRADLE_FILE)) {
            initialSize += 5;
        }
        return initialSize;
    }
}
 
Example #3
Source File: MissingClassDetectorTest.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
public void testFragments() throws Exception {
    mScopes = Scope.MANIFEST_SCOPE;
    mEnabled = Sets.newHashSet(MISSING, INSTANTIATABLE, INNERCLASS);

    // Ensure that we don't do instantiation checks here since they are handled by
    // the FragmentDetector
    assertEquals(
            "No warnings.",

            lintProject(
                    "bytecode/FragmentTest$Fragment1.class.data=>bin/classes/test/pkg/FragmentTest$Fragment1.class",
                    "bytecode/FragmentTest$Fragment2.class.data=>bin/classes/test/pkg/FragmentTest$Fragment2.class",
                    "bytecode/FragmentTest$Fragment3.class.data=>bin/classes/test/pkg/FragmentTest$Fragment3.class",
                    "bytecode/FragmentTest$Fragment4.class.data=>bin/classes/test/pkg/FragmentTest$Fragment4.class",
                    "bytecode/FragmentTest$Fragment5.class.data=>bin/classes/test/pkg/FragmentTest$Fragment5.class",
                    "bytecode/FragmentTest$Fragment6.class.data=>bin/classes/test/pkg/FragmentTest$Fragment6.class",
                    "bytecode/FragmentTest$NotAFragment.class.data=>bin/classes/test/pkg/FragmentTest$NotAFragment.class",
                    "bytecode/FragmentTest.java.txt=>src/test/pkg/FragmentTest.java"));
}
 
Example #4
Source File: LintDriver.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
/**
 * Requests another pass through the data for the given detector. This is
 * typically done when a detector needs to do more expensive computation,
 * but it only wants to do this once it <b>knows</b> that an error is
 * present, or once it knows more specifically what to check for.
 *
 * @param detector the detector that should be included in the next pass.
 *            Note that the lint runner may refuse to run more than a couple
 *            of runs.
 * @param scope the scope to be revisited. This must be a subset of the
 *       current scope ({@link #getScope()}, and it is just a performance hint;
 *       in particular, the detector should be prepared to be called on other
 *       scopes as well (since they may have been requested by other detectors).
 *       You can pall null to indicate "all".
 */
public void requestRepeat(@NonNull Detector detector, @Nullable EnumSet<Scope> scope) {
    if (mRepeatingDetectors == null) {
        mRepeatingDetectors = new ArrayList<Detector>();
    }
    mRepeatingDetectors.add(detector);

    if (scope != null) {
        if (mRepeatScope == null) {
            mRepeatScope = scope;
        } else {
            mRepeatScope = EnumSet.copyOf(mRepeatScope);
            mRepeatScope.addAll(scope);
        }
    } else {
        mRepeatScope = Scope.ALL;
    }
}
 
Example #5
Source File: LintDriver.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
private void checkIndividualClassFiles(
        @NonNull Project project,
        @Nullable Project main,
        @NonNull List<File> files) {
    List<File> classFiles = Lists.newArrayListWithExpectedSize(files.size());
    List<File> classFolders = project.getJavaClassFolders();
    if (!classFolders.isEmpty()) {
        for (File file : files) {
            String path = file.getPath();
            if (file.isFile() && path.endsWith(DOT_CLASS)) {
                classFiles.add(file);
            }
        }
    }

    List<ClassEntry> entries = ClassEntry.fromClassFiles(mClient, classFiles, classFolders,
            true);
    if (!entries.isEmpty()) {
        Collections.sort(entries);
        runClassDetectors(Scope.CLASS_FILE, entries, project, main);
    }
}
 
Example #6
Source File: LintDriver.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
private void checkBuildScripts(Project project, Project main) {
    List<Detector> detectors = mScopeDetectors.get(Scope.GRADLE_FILE);
    if (detectors != null) {
        List<File> files = project.getSubset();
        if (files == null) {
            files = project.getGradleBuildScripts();
        }
        for (File file : files) {
            Context context = new Context(this, project, main, file);
            fireEvent(EventType.SCANNING_FILE, context);
            for (Detector detector : detectors) {
                if (detector.appliesTo(context, file)) {
                    detector.beforeCheckFile(context);
                    detector.visitBuildScript(context, Maps.<String, Object>newHashMap());
                    detector.afterCheckFile(context);
                }
            }
        }
    }
}
 
Example #7
Source File: LintDriver.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
private void checkProGuard(Project project, Project main) {
    List<Detector> detectors = mScopeDetectors.get(Scope.PROGUARD_FILE);
    if (detectors != null) {
        List<File> files = project.getProguardFiles();
        for (File file : files) {
            Context context = new Context(this, project, main, file);
            fireEvent(EventType.SCANNING_FILE, context);
            for (Detector detector : detectors) {
                if (detector.appliesTo(context, file)) {
                    detector.beforeCheckFile(context);
                    detector.run(context);
                    detector.afterCheckFile(context);
                }
            }
        }
    }
}
 
Example #8
Source File: RequiredAttributeDetector.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@Override
public void afterCheckProject(@NonNull Context context) {
    // Process checks in two phases:
    // Phase 1: Gather styles and includes (styles are encountered after the layouts
    // so we can't do it in a single phase, and includes can be affected by includes from
    // layouts we haven't seen yet)
    // Phase 2: Process layouts, using gathered style and include data, and mark layouts
    // not known.
    //
    if (context.getPhase() == 1) {
        checkSizeSetInTheme();

        context.requestRepeat(this, Scope.RESOURCE_FILE_SCOPE);
    }
}
 
Example #9
Source File: WakelockDetector.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@Override
public void afterCheckProject(@NonNull Context context) {
    if (mHasAcquire && !mHasRelease && context.getDriver().getPhase() == 1) {
        // Gather positions of the acquire calls
        context.getDriver().requestRepeat(this, Scope.CLASS_FILE_SCOPE);
    }
}
 
Example #10
Source File: ResourceCycleDetector.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@Override
public void beforeCheckProject(@NonNull Context context) {
    // In incremental mode, or checking all files (full lint analysis) ? If the latter,
    // we should store state and look for deeper cycles
    if (context.getScope().contains(Scope.ALL_RESOURCE_FILES)) {
        mReferences = Maps.newEnumMap(ResourceType.class);
    }
}
 
Example #11
Source File: ResourceCycleDetector.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
private void findCycles(
        @NonNull Context context,
        @NonNull ResourceType type,
        @NonNull Multimap<String, String> map) {
    Set<String> visiting = Sets.newHashSetWithExpectedSize(map.size());
    Set<String> seen = Sets.newHashSetWithExpectedSize(map.size());
    for (String from : map.keySet()) {
        if (seen.contains(from)) {
            continue;
        }
        List<String> chain = dfs(map, from, visiting);
        if (chain != null && chain.size() > 2) { // size 1 chains are handled directly
            seen.addAll(chain);
            Collections.reverse(chain);
            if (mChains == null) {
                mChains = Maps.newEnumMap(ResourceType.class);
                mLocations = Maps.newEnumMap(ResourceType.class);
                context.getDriver().requestRepeat(this, Scope.RESOURCE_FILE_SCOPE);
            }
            List<List<String>> list = mChains.get(type);
            if (list == null) {
                list = Lists.newArrayList();
                mChains.put(type, list);
            }
            list.add(chain);
        }
    }
}
 
Example #12
Source File: LayoutConsistencyDetector.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@Override
public void afterCheckProject(@NonNull Context context) {
    LintDriver driver = context.getDriver();
    if (driver.getPhase() == 1) {
        // First phase: gather all the ids and look for consistency issues.
        // If any are found, request location computation in phase 2 by
        // writing the ids needed for each layout in the {@link #mLocations} map.
        for (Map.Entry<String,List<Pair<File,Map<String,String>>>> entry : mMap.entrySet()) {
            String layout = entry.getKey();
            List<Pair<File, Map<String, String>>> files = entry.getValue();
            if (files.size() < 2) {
                // No consistency problems for files that don't have resource variations
                continue;
            }

            checkConsistentIds(layout, files);
        }

        if (mLocations != null) {
            driver.requestRepeat(this, Scope.ALL_RESOURCES_SCOPE);
        }
    } else {
        // Collect results and print
        if (!mLocations.isEmpty()) {
            reportErrors(context);
        }
    }
}
 
Example #13
Source File: LintDriver.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
private void checkProperties(Project project, Project main) {
    List<Detector> detectors = mScopeDetectors.get(Scope.PROPERTY_FILE);
    if (detectors != null) {
        checkPropertyFile(project, main, detectors, FN_LOCAL_PROPERTIES);
        checkPropertyFile(project, main, detectors, FD_GRADLE_WRAPPER + separator +
                FN_GRADLE_WRAPPER_PROPERTIES);
    }
}
 
Example #14
Source File: LintDriver.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
private void computeDetectors(@NonNull Project project) {
    // Ensure that the current visitor is recomputed
    mCurrentFolderType = null;
    mCurrentVisitor = null;

    Configuration configuration = project.getConfiguration(this);
    mScopeDetectors = new EnumMap<Scope, List<Detector>>(Scope.class);
    mApplicableDetectors = mRegistry.createDetectors(mClient, configuration,
            mScope, mScopeDetectors);

    validateScopeList();
}
 
Example #15
Source File: MissingClassDetectorTest.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
public void testIncrementalInManifest() throws Exception {
    mScopes = Scope.MANIFEST_SCOPE;
    mEnabled = Sets.newHashSet(MISSING, INSTANTIATABLE, INNERCLASS);
    assertEquals(
            "No warnings.",

            lintProject(
                "bytecode/AndroidManifestWrongRegs.xml=>AndroidManifest.xml",
                "bytecode/.classpath=>.classpath"
            ));
}
 
Example #16
Source File: BuiltinIssueRegistryTest.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@SuppressWarnings("unchecked")
public void testCapacities() throws IllegalAccessException {
    TestIssueRegistry registry = new TestIssueRegistry();
    for (Scope scope : Scope.values()) {
        EnumSet<Scope> scopeSet = EnumSet.of(scope);
        checkCapacity(registry, scopeSet);
    }

    // Also check the commonly used combinations
    for (Field field : Scope.class.getDeclaredFields()) {
        if (field.getType().isAssignableFrom(EnumSet.class)) {
            checkCapacity(registry, (EnumSet<Scope>) field.get(null));
        }
    }
}
 
Example #17
Source File: BuiltinIssueRegistryTest.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
private static void checkCapacity(TestIssueRegistry registry,
        EnumSet<Scope> scopeSet) {
    List<Issue> issuesForScope = registry.getIssuesForScope(scopeSet);
    int requiredSize = issuesForScope.size();
    int capacity = registry.getIssueCapacity(scopeSet);
    if (requiredSize > capacity) {
        fail("For Scope set " + scopeSet + ": capacity " + capacity
                + " < actual " + requiredSize);
    }
}
 
Example #18
Source File: ButtonDetector.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@Override
public void afterCheckProject(@NonNull Context context) {
    int phase = context.getPhase();
    if (phase == 1 && mApplicableResources != null) {
        // We found resources for the string "Cancel"; perform a second pass
        // where we check layout text attributes against these strings.
        context.getDriver().requestRepeat(this, Scope.RESOURCE_FILE_SCOPE);
    }
}
 
Example #19
Source File: PrivateKeyDetector.java    From javaide with GNU General Public License v3.0 4 votes vote down vote up
@NonNull
@Override
public EnumSet<Scope> getApplicableFiles() {
    return Scope.OTHER_SCOPE;
}
 
Example #20
Source File: MissingClassDetectorTest.java    From javaide with GNU General Public License v3.0 4 votes vote down vote up
@Override
protected EnumSet<Scope> getLintScope(List<File> file) {
    return mScopes;
}
 
Example #21
Source File: AnnotationDetector.java    From javaide with GNU General Public License v3.0 4 votes vote down vote up
private boolean checkId(Annotation node, String id) {
    IssueRegistry registry = mContext.getDriver().getRegistry();
    Issue issue = registry.getIssue(id);
    // Special-case the ApiDetector issue, since it does both source file analysis
    // only on field references, and class file analysis on the rest, so we allow
    // annotations outside of methods only on fields
    if (issue != null && !issue.getImplementation().getScope().contains(Scope.JAVA_FILE)
            || issue == ApiDetector.UNSUPPORTED) {
        // Ensure that this isn't a field
        Node parent = node.getParent();
        while (parent != null) {
            if (parent instanceof MethodDeclaration
                    || parent instanceof ConstructorDeclaration
                    || parent instanceof Block) {
                break;
            } else if (parent instanceof TypeBody) { // It's a field
                return true;
            } else if (issue == ApiDetector.UNSUPPORTED
                    && parent instanceof VariableDefinition) {
                VariableDefinition definition = (VariableDefinition) parent;
                for (VariableDefinitionEntry entry : definition.astVariables()) {
                    Expression initializer = entry.astInitializer();
                    if (initializer instanceof Select) {
                        return true;
                    }
                }
            }
            parent = parent.getParent();
            if (parent == null) {
                return true;
            }
        }

        // This issue doesn't have AST access: annotations are not
        // available for local variables or parameters
        Node scope = getAnnotationScope(node);
        mContext.report(INSIDE_METHOD, scope, mContext.getLocation(node), String.format(
            "The `@SuppressLint` annotation cannot be used on a local " +
            "variable with the lint check '%1$s': move out to the " +
            "surrounding method", id));
        return false;
    }

    return true;
}
 
Example #22
Source File: LintDetectorTest.java    From javaide with GNU General Public License v3.0 4 votes vote down vote up
protected EnumSet<Scope> getLintScope(List<File> file) {
    return null;
}
 
Example #23
Source File: WrongIdDetector.java    From javaide with GNU General Public License v3.0 4 votes vote down vote up
@Override
public void afterCheckProject(@NonNull Context context) {
    if (context.getScope().contains(Scope.ALL_RESOURCE_FILES)) {
        checkHandles(context);
    }
}
 
Example #24
Source File: BuiltinIssueRegistryTest.java    From javaide with GNU General Public License v3.0 4 votes vote down vote up
@NonNull
@Override
public List<Issue> getIssuesForScope(@NonNull EnumSet<Scope> scope) {
    return super.getIssuesForScope(scope);
}
 
Example #25
Source File: EnumDetector.java    From linette with Apache License 2.0 4 votes vote down vote up
@Override
public EnumSet<Scope> getApplicableFiles() {
    return Scope.JAVA_FILE_SCOPE;
}
 
Example #26
Source File: MissingClassDetector.java    From javaide with GNU General Public License v3.0 4 votes vote down vote up
@Override
public void afterCheckProject(@NonNull Context context) {
    if (!context.getProject().isLibrary() && mHaveClasses
            && mReferencedClasses != null && !mReferencedClasses.isEmpty()
            && context.getDriver().getScope().contains(Scope.CLASS_FILE)) {
        List<String> classes = new ArrayList<String>(mReferencedClasses.keySet());
        Collections.sort(classes);
        for (String owner : classes) {
            Location.Handle handle = mReferencedClasses.get(owner);
            String fqcn = ClassContext.getFqcn(owner);

            String signature = ClassContext.getInternalName(fqcn);
            if (!signature.equals(owner)) {
                if (!mReferencedClasses.containsKey(signature)) {
                    continue;
                }
            } else if (signature.indexOf('$') != -1) {
                signature = signature.replace('$', '/');
                if (!mReferencedClasses.containsKey(signature)) {
                    continue;
                }
            }
            mReferencedClasses.remove(owner);

            // Ignore usages of platform libraries
            if (owner.startsWith("android/")) { //$NON-NLS-1$
                continue;
            }

            String message = String.format(
                    "Class referenced in the manifest, `%1$s`, was not found in the " +
                            "project or the libraries", fqcn);
            Location location = handle.resolve();
            File parentFile = location.getFile().getParentFile();
            if (parentFile != null) {
                String parent = parentFile.getName();
                ResourceFolderType type = ResourceFolderType.getFolderType(parent);
                if (type == LAYOUT) {
                    message = String.format(
                        "Class referenced in the layout file, `%1$s`, was not found in "
                            + "the project or the libraries", fqcn);
                } else if (type == XML) {
                    message = String.format(
                            "Class referenced in the preference header file, `%1$s`, was not "
                                    + "found in the project or the libraries", fqcn);

                } else if (type == VALUES) {
                    message = String.format(
                            "Class referenced in the analytics file, `%1$s`, was not "
                                    + "found in the project or the libraries", fqcn);
                }
            }

            context.report(MISSING, location, message);
        }
    }
}
 
Example #27
Source File: IssueDetector.java    From aircon with MIT License 4 votes vote down vote up
private static Issue createIssue(String id, String briefDesc, String explanation, Severity severity) {
	return Issue.create(id, briefDesc, explanation, Category.CORRECTNESS, 6, severity, new Implementation(AirConUsageDetector.class, Scope.JAVA_FILE_SCOPE));
}
 
Example #28
Source File: LintDriver.java    From javaide with GNU General Public License v3.0 4 votes vote down vote up
/** Check the classes in this project (and if applicable, in any library projects */
private void checkClasses(Project project, Project main) {
    List<File> files = project.getSubset();
    if (files != null) {
        checkIndividualClassFiles(project, main, files);
        return;
    }

    // We need to read in all the classes up front such that we can initialize
    // the parent chains (such that for example for a virtual dispatch, we can
    // also check the super classes).

    List<File> libraries = project.getJavaLibraries();
    List<ClassEntry> libraryEntries = ClassEntry.fromClassPath(mClient, libraries, true);

    List<File> classFolders = project.getJavaClassFolders();
    List<ClassEntry> classEntries;
    if (classFolders.isEmpty()) {
        String message = String.format("No `.class` files were found in project \"%1$s\", "
                + "so none of the classfile based checks could be run. "
                + "Does the project need to be built first?", project.getName());
        Location location = Location.create(project.getDir());
        mClient.report(new Context(this, project, main, project.getDir()),
                IssueRegistry.LINT_ERROR,
                project.getConfiguration(this).getSeverity(IssueRegistry.LINT_ERROR),
                location, message, TextFormat.RAW);
        classEntries = Collections.emptyList();
    } else {
        classEntries = ClassEntry.fromClassPath(mClient, classFolders, true);
    }

    // Actually run the detectors. Libraries should be called before the
    // main classes.
    runClassDetectors(Scope.JAVA_LIBRARIES, libraryEntries, project, main);

    if (mCanceled) {
        return;
    }

    runClassDetectors(Scope.CLASS_FILE, classEntries, project, main);
    runClassDetectors(Scope.ALL_CLASS_FILES, classEntries, project, main);
}
 
Example #29
Source File: LintDriver.java    From javaide with GNU General Public License v3.0 4 votes vote down vote up
private void runExtraPhases(@NonNull Project project, @NonNull Project main) {
    // Did any detectors request another phase?
    if (mRepeatingDetectors != null) {
        // Yes. Iterate up to MAX_PHASES times.

        // During the extra phases, we might be narrowing the scope, and setting it in the
        // scope field such that detectors asking about the available scope will get the
        // correct result. However, we need to restore it to the original scope when this
        // is done in case there are other projects that will be checked after this, since
        // the repeated phases is done *per project*, not after all projects have been
        // processed.
        EnumSet<Scope> oldScope = mScope;

        do {
            mPhase++;
            fireEvent(EventType.NEW_PHASE,
                    new Context(this, project, null, project.getDir()));

            // Narrow the scope down to the set of scopes requested by
            // the rules.
            if (mRepeatScope == null) {
                mRepeatScope = Scope.ALL;
            }
            mScope = Scope.intersect(mScope, mRepeatScope);
            if (mScope.isEmpty()) {
                break;
            }

            // Compute the detectors to use for this pass.
            // Unlike the normal computeDetectors(project) call,
            // this is going to use the existing instances, and include
            // those that apply for the configuration.
            computeRepeatingDetectors(mRepeatingDetectors, project);

            if (mApplicableDetectors.isEmpty()) {
                // No detectors enabled in this project: skip it
                continue;
            }

            checkProject(project, main);
            if (mCanceled) {
                break;
            }
        } while (mPhase < MAX_PHASES && mRepeatingDetectors != null);

        mScope = oldScope;
    }
}
 
Example #30
Source File: IssueRegistry.java    From javaide with GNU General Public License v3.0 4 votes vote down vote up
/**
 * Creates a list of detectors applicable to the given scope, and with the
 * given configuration.
 *
 * @param client the client to report errors to
 * @param configuration the configuration to look up which issues are
 *            enabled etc from
 * @param scope the scope for the analysis, to filter out detectors that
 *            require wider analysis than is currently being performed
 * @param scopeToDetectors an optional map which (if not null) will be
 *            filled by this method to contain mappings from each scope to
 *            the applicable detectors for that scope
 * @return a list of new detector instances
 */
@NonNull
final List<? extends Detector> createDetectors(
        @NonNull LintClient client,
        @NonNull Configuration configuration,
        @NonNull EnumSet<Scope> scope,
        @Nullable Map<Scope, List<Detector>> scopeToDetectors) {

    List<Issue> issues = getIssuesForScope(scope);
    if (issues.isEmpty()) {
        return Collections.emptyList();
    }

    Set<Class<? extends Detector>> detectorClasses = new HashSet<Class<? extends Detector>>();
    Map<Class<? extends Detector>, EnumSet<Scope>> detectorToScope =
            new HashMap<Class<? extends Detector>, EnumSet<Scope>>();

    for (Issue issue : issues) {
        Implementation implementation = issue.getImplementation();
        Class<? extends Detector> detectorClass = implementation.getDetectorClass();
        EnumSet<Scope> issueScope = implementation.getScope();
        if (!detectorClasses.contains(detectorClass)) {
            // Determine if the issue is enabled
            if (!configuration.isEnabled(issue)) {
                continue;
            }

            assert implementation.isAdequate(scope); // Ensured by getIssuesForScope above

            detectorClass = client.replaceDetector(detectorClass);

            assert detectorClass != null : issue.getId();
            detectorClasses.add(detectorClass);
        }

        if (scopeToDetectors != null) {
            EnumSet<Scope> s = detectorToScope.get(detectorClass);
            if (s == null) {
                detectorToScope.put(detectorClass, issueScope);
            } else if (!s.containsAll(issueScope)) {
                EnumSet<Scope> union = EnumSet.copyOf(s);
                union.addAll(issueScope);
                detectorToScope.put(detectorClass, union);
            }
        }
    }

    List<Detector> detectors = new ArrayList<Detector>(detectorClasses.size());
    for (Class<? extends Detector> clz : detectorClasses) {
        try {
            Detector detector = clz.newInstance();
            detectors.add(detector);

            if (scopeToDetectors != null) {
                EnumSet<Scope> union = detectorToScope.get(clz);
                for (Scope s : union) {
                    List<Detector> list = scopeToDetectors.get(s);
                    if (list == null) {
                        list = new ArrayList<Detector>();
                        scopeToDetectors.put(s, list);
                    }
                    list.add(detector);
                }

            }
        } catch (Throwable t) {
            client.log(t, "Can't initialize detector %1$s", clz.getName()); //$NON-NLS-1$
        }
    }

    return detectors;
}