@Override public boolean getReportIssues() { if (projectDescription != null && !projectDescription.report) { return false; } return super.getReportIssues(); }
@Override public void afterCheckFile(@NonNull Context context) { if (context.getPhase() == 1) { // Store this layout's set of ids for full project analysis in afterCheckProject if (context.getProject().getReportIssues() && mNames != null && !mNames.isEmpty()) { mFileToNames.put(context.file, mNames); Element root = ((XmlContext) context).document.getDocumentElement(); if (root != null) { String locale = root.getAttributeNS(TOOLS_URI, ATTR_LOCALE); if (locale != null && !locale.isEmpty()) { if (mFileToLocale == null) { mFileToLocale = Maps.newHashMap(); } mFileToLocale.put(context.file, locale); } // Add in English here if not specified? Worry about false positives listing "en" explicitly } } mNames = null; } }
@Override public void visitElement(@NonNull XmlContext context, @NonNull Element element) { String layout = element.getAttribute(ATTR_LAYOUT); if (layout.startsWith(LAYOUT_RESOURCE_PREFIX)) { // Ignore @android:layout/ layouts layout = layout.substring(LAYOUT_RESOURCE_PREFIX.length()); Node parent = element.getParentNode(); if (parent.getNodeType() == Node.ELEMENT_NODE) { String tag = parent.getNodeName(); if (tag.indexOf('.') == -1 && !tag.equals(VIEW_MERGE)) { if (!context.getProject().getReportIssues()) { // If this is a library project not being analyzed, ignore it return; } if (mIncludes == null) { mIncludes = new HashMap<>(); } List<Pair<File, String>> includes = mIncludes.get(layout); if (includes == null) { includes = new ArrayList<>(); mIncludes.put(layout, includes); } includes.add(Pair.of(context.file, tag)); } } } }
@Override public void afterCheckFile(@NonNull Context context) { if (context.getPhase() == 1) { // Store this layout's set of ids for full project analysis in afterCheckProject if (context.getProject().getReportIssues() && mNames != null && !mNames.isEmpty()) { mFileToNames.put(context.file, mNames); Element root = ((XmlContext) context).document.getDocumentElement(); if (root != null) { String locale = root.getAttributeNS(TOOLS_URI, ATTR_LOCALE); if (locale != null && !locale.isEmpty()) { if (mFileToLocale == null) { mFileToLocale = Maps.newHashMap(); } mFileToLocale.put(context.file, locale); } // Add in English here if not specified? Worry about false positives listing "en" explicitly } } mNames = null; } }
@Override public void beforeCheckFile(@NonNull Context context) { if (context.getPhase() == 1) { mNames = new HashSet<>(); } // Convention seen in various projects mIgnoreFile = context.file.getName().startsWith("donottranslate") || ResourceUsageModel.isAnalyticsFile(context.file); if (!context.getProject().getReportIssues()) { mIgnoreFile = true; } }
@Override public void beforeCheckFile(@NonNull Context context) { if (context.getPhase() == 1) { mNames = new HashSet<String>(); } // Convention seen in various projects mIgnoreFile = context.file.getName().startsWith("donottranslate") //$NON-NLS-1$ || UnusedResourceDetector.isAnalyticsFile(context); if (!context.getProject().getReportIssues()) { mIgnoreFile = true; } }
@Override public void visitElement(@NonNull XmlContext context, @NonNull Element element) { String layout = element.getAttribute(ATTR_LAYOUT); if (layout.startsWith(LAYOUT_RESOURCE_PREFIX)) { // Ignore @android:layout/ layouts layout = layout.substring(LAYOUT_RESOURCE_PREFIX.length()); Node parent = element.getParentNode(); if (parent.getNodeType() == Node.ELEMENT_NODE) { String tag = parent.getNodeName(); if (tag.indexOf('.') == -1 && !tag.equals(VIEW_MERGE)) { if (!context.getProject().getReportIssues()) { // If this is a library project not being analyzed, ignore it return; } if (mIncludes == null) { mIncludes = new HashMap<String, List<Pair<File, String>>>(); } List<Pair<File, String>> includes = mIncludes.get(layout); if (includes == null) { includes = new ArrayList<Pair<File, String>>(); mIncludes.put(layout, includes); } includes.add(Pair.of(context.file, tag)); } } } }
@Override public void run(@NonNull Context context) { if (!context.getProject().getReportIssues()) { // If this is a library project not being analyzed, ignore it return; } File file = context.file; if (isPrivateKeyFile(file)) { String fileName = file.getParentFile().getName() + File.separator + file.getName(); String message = String.format( "The `%1$s` file seems to be a private key file. " + "Please make sure not to embed this in your APK file.", fileName); context.report(ISSUE, Location.create(file), message); } }
@Override public void run(@NonNull Context context) { if (!context.getProject().getReportIssues()) { // If this is a library project not being analyzed, ignore it return; } File file = context.file; if (isPrivateKeyFile(file)) { String fileName = file.getParentFile().getName() + File.separator + file.getName(); String message = String.format( "The `%1$s` file seems to be a private key file. " + "Please make sure not to embed this in your APK file.", fileName); context.report(ISSUE, Location.create(file), message); } }
@Override public AstVisitor createJavaVisitor(@NonNull JavaContext context) { if (!context.getProject().getReportIssues()) { return null; } return new OverdrawVisitor(); }
private void checkAssetsFolder(@NonNull Context context) { if (!context.getProject().getReportIssues()) { // If this is a library project not being analyzed, ignore it return; } Project project = context.getProject(); List<File> assetFolders = project.getAssetFolders(); Deque<File> files = new ArrayDeque<>(); for (File assetFolder : assetFolders) { // The js file could be at an arbitrary level in the directory tree. // examples: // assets/www/cordova.js // assets/www/plugins/phonegap/cordova.js.2.2.android files.push(assetFolder); while (!files.isEmpty() && mCordovaVersion == null) { File current = files.pop(); if (current.isDirectory()) { File[] filtered = current.listFiles(CORDOVA_JS_FILTER); if (filtered != null) { for (File file : filtered) { files.push(file); } } } else { checkFile(context, current); } } files.clear(); } }
@Override public void afterCheckLibraryProject(@NonNull Context context) { if (!context.getProject().getReportIssues()) { // If this is a library project not being analyzed, ignore it return; } checkResourceFolder(context, context.getProject()); }
@Override public void afterCheckLibraryProject(@NonNull Context context) { if (!context.getProject().getReportIssues()) { // If this is a library project not being analyzed, ignore it return; } checkResourceFolder(context, context.getProject()); }
@Override public void afterCheckLibraryProject(@NonNull Context context) { if (!context.getProject().getReportIssues()) { // If this is a library project not being analyzed, ignore it return; } checkResourceFolders(context, context.getProject()); }
@Override public void afterCheckProject(@NonNull Context context) { if (!context.getProject().getReportIssues()) { // If this is a library project not being analyzed, ignore it return; } checkResourceFolders(context, context.getProject()); }
@Override public void visitDocument(@NonNull XmlContext context, @NonNull Document document) { if (!context.getProject().getReportIssues()) { return; } Element root = document.getDocumentElement(); if (root != null) { if (context.getPhase() == 1) { // Map from ids to types Map<String,String> fileMap = Maps.newHashMapWithExpectedSize(10); addIds(root, fileMap); getFileMapList(context).add(Pair.of(context.file, fileMap)); } else { String name = LintUtils.getLayoutName(context.file); Map<String, List<Location>> map = mLocations.get(name); if (map != null) { lookupLocations(context, root, map); } } } }
handle.setClientData(element); if (!context.getProject().getReportIssues()) {
@Override public void checkClass(@NonNull JavaContext context, @NonNull PsiClass declaration) { if (!context.getProject().getReportIssues()) { return; } String name = declaration.getQualifiedName(); if (name != null) { declaration.accept(new OverdrawVisitor(name, declaration)); } }
@Override public void checkClass(@NonNull JavaContext context, @NonNull PsiClass declaration) { if (!context.getProject().getReportIssues()) { return; } JavaEvaluator evaluator = context.getEvaluator(); String className = declaration.getQualifiedName(); if (evaluator.extendsClass(declaration, PREFERENCE_ACTIVITY, false) && mExportedActivities.containsKey(className)) { // Ignore the issue if we target an API greater than 19 and the class in // question specifically overrides isValidFragment() and thus knowingly white-lists // valid fragments. if (context.getMainProject().getTargetSdk() >= 19 && overridesIsValidFragment(evaluator, declaration)) { return; } String message = String.format( "`PreferenceActivity` subclass `%1$s` should not be exported", className); Location location = mExportedActivities.get(className).resolve(); context.report(ISSUE, declaration, location, message); } }
@Override public void checkClass(@NonNull JavaContext context, @Nullable ClassDeclaration node, @NonNull Node declarationOrAnonymous, @NonNull ResolvedClass resolvedClass) { if (!context.getProject().getReportIssues()) { return; } String className = resolvedClass.getName(); if (resolvedClass.isSubclassOf(PREFERENCE_ACTIVITY, false) && mExportedActivities.containsKey(className)) { // Ignore the issue if we target an API greater than 19 and the class in // question specifically overrides isValidFragment() and thus knowingly white-lists // valid fragments. if (context.getMainProject().getTargetSdk() >= 19 && overridesIsValidFragment(resolvedClass)) { return; } String message = String.format( "`PreferenceActivity` subclass `%1$s` should not be exported", className); context.report(ISSUE, mExportedActivities.get(className).resolve(), message); } }