/** * 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) { driver.requestRepeat(detector, scope); }
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); } } }
private void findCycles( @NonNull Context context, @NonNull ResourceType type, @NonNull Multimap<String, String> map) { Set<String> visiting = Sets.newHashSet(); Set<String> visited = 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, visited); 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); } } }
@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); } }
@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); } }
@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); } } }
@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); } } }
@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); } }
mErrors = new ArrayList<Occurrence>(); mLocations = ArrayListMultimap.create(); mContext.getDriver().requestRepeat(DuplicateIdDetector.this, Scope.ALL_RESOURCES_SCOPE);
@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); } }
mErrors = new ArrayList<>(); mLocations = ArrayListMultimap.create(); mContext.getDriver().requestRepeat(DuplicateIdDetector.this, Scope.ALL_RESOURCES_SCOPE);
context.getDriver().requestRepeat(this, Scope.ALL_RESOURCES_SCOPE);
context.getDriver().requestRepeat(this, Scope.ALL_RESOURCES_SCOPE);
@Override public void afterCheckProject(@NonNull Context context) { if (context.getPhase() == 1) { // NOTE - this will look for the presence of translation strings. // If you create a resource folder but don't actually place a file in it // we won't detect that, but it seems like a smaller problem. checkTranslations(context); mFileToNames = null; if (mMissingLocations != null || mExtraLocations != null) { context.getDriver().requestRepeat(this, Scope.ALL_RESOURCES_SCOPE); } } else { assert context.getPhase() == 2; reportMap(context, MISSING, mMissingLocations); reportMap(context, EXTRA, mExtraLocations); mMissingLocations = null; mExtraLocations = null; mDescriptions = null; } }
@Override public void afterCheckProject(@NonNull Context context) { if (context.getPhase() == 1) { // NOTE - this will look for the presence of translation strings. // If you create a resource folder but don't actually place a file in it // we won't detect that, but it seems like a smaller problem. checkTranslations(context); mFileToNames = null; if (mMissingLocations != null || mExtraLocations != null) { context.getDriver().requestRepeat(this, Scope.ALL_RESOURCES_SCOPE); } } else { assert context.getPhase() == 2; reportMap(context, MISSING, mMissingLocations); reportMap(context, EXTRA, mExtraLocations); mMissingLocations = null; mExtraLocations = null; mDescriptions = null; } }