All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sourceforge.pmd.lang.apex.multifile.ApexMultifileAnalysis Maven / Gradle / Ivy

There is a newer version: 7.5.0
Show newest version
/**
 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
 */

package net.sourceforge.pmd.lang.apex.multifile;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import org.checkerframework.checker.nullness.qual.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.sourceforge.pmd.lang.apex.ApexLanguageProcessor;
import net.sourceforge.pmd.lang.apex.ApexLanguageProperties;

import com.nawforce.apexlink.api.Org;
import com.nawforce.pkgforce.diagnostics.LoggerOps;
import io.github.apexdevtools.api.Issue;

/**
 * Stores multi-file analysis data. The 'Org' here is the primary ApexLink structure for maintaining information
 * about the Salesforce metadata. We load 'Packages' into it to perform analysis. Once constructed you
 * can get 'Issue' information from it on what was found. The 'Org' holds mutable state for IDE use that can get quite
 * large (a few hundred MB on very large projects). An alternative way to use this would be to cache the
 * issues after packages are loaded and throw away the 'Org'. That would be a better model if all you wanted was the
 * issues but more complex rules will need the ability to traverse the internal graph of the 'Org'.
 *
 * 

Note: This is used by {@link net.sourceforge.pmd.lang.apex.rule.design.UnusedMethodRule}. * * @author Kevin Jones */ public final class ApexMultifileAnalysis { // test only static final Logger LOG = LoggerFactory.getLogger(ApexMultifileAnalysis.class); // Create a new org for each analysis // Null if failed. private final @Nullable Org org; static { // Setup logging LoggerOps.setLogger(new AnalysisLogger()); // TODO: Provide means to control logging LoggerOps.setLoggingLevel(LoggerOps.NO_LOGGING()); } ApexMultifileAnalysis(ApexLanguageProperties properties) { Optional rootDir = properties.getProperty(ApexLanguageProperties.MULTIFILE_DIRECTORY); LOG.debug("MultiFile Analysis created for {}", rootDir); Org org = null; try { // Load the package into the org, this can take some time! if (rootDir.isPresent() && !rootDir.get().isEmpty()) { Path projectPath = Paths.get(rootDir.get()); Path sfdxProjectJson = projectPath.resolve("sfdx-project.json"); // Limit analysis to SFDX Projects // MDAPI analysis is currently supported but is expected to be deprecated soon if (Files.isDirectory(projectPath) && Files.isRegularFile(sfdxProjectJson)) { org = Org.newOrg(rootDir.get()); // FIXME: Syntax & Semantic errors found during Org loading are not currently being reported. These // should be routed to the new SemanticErrorReporter but that is not available for use just yet. // Specifically we should check sfdx-project.json was ok as errors will disable further analysis Issue[] projectErrors = Arrays.stream(org.issues().issuesForFile(sfdxProjectJson.toString())) .filter(Issue::isError).toArray(Issue[]::new); Arrays.stream(projectErrors).forEach(issue -> LOG.info(issue.toString())); if (projectErrors.length != 0) { org = null; } } else { LOG.info("Missing project file at {}", sfdxProjectJson); } } } catch (Exception | ExceptionInInitializerError | NoClassDefFoundError e) { // Note: Org.newOrg() will try to find the base Apex Types through the current classloader // in package "com.nawforce.runforce". This requires, that directory listings can be retrievied // on the URL that the classloader returns from getResource("/com/nawforce/runforce"): // https://github.com/nawforce/apex-link/blob/7688adcb7a2d7f8aa28d0618ffb2a3aa81151858/apexlink/src/main/scala/com/nawforce/apexlink/types/platform/PlatformTypeDeclaration.scala#L260-L273 // However, when running as an Eclipse plugin, we have a special bundle classloader, that returns // URIs in the form "bundleresource://...". For the schema "bundleresource", no FileSystemProvider can be // found, so we get a java.nio.file.ProviderNotFoundException. Since all this happens during initialization of the class // com.nawforce.apexlink.types.platform.PlatformTypeDeclaration we get a ExceptionInInitializerError // and later NoClassDefFoundErrors, because PlatformTypeDeclaration couldn't be loaded. LOG.error("Exception while initializing Apexlink ({})", e.getMessage(), e); LOG.error("PMD will not attempt to initialize Apexlink further, this can cause rules like UnusedMethod to be dysfunctional"); } this.org = org; } /** * Returns true if this is analysis index is in a failed state. * This object is then useless. The failed instance is returned * from {@link ApexLanguageProcessor#getMultiFileState()} if * loading the org failed, maybe because of malformed configuration. */ public boolean isFailed() { return org == null; } public List getFileIssues(String filename) { // Extract issues for a specific metadata file from the org return org == null ? Collections.emptyList() : Collections.unmodifiableList(Arrays.asList(org.issues().issuesForFile(filename))); } /* * Very simple logger to aid debugging, relays ApexLink logging into PMD */ private static final class AnalysisLogger implements com.nawforce.pkgforce.diagnostics.Logger { @Override public void info(String message) { LOG.info(message); } @Override public void debug(String message) { LOG.debug(message); } @Override public void trace(String message) { LOG.trace(message); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy