View Javadoc
1   /*
2    * SPDX-FileCopyrightText: Copyright (c) 2011-2026 Yegor Bugayenko
3    * SPDX-License-Identifier: MIT
4    */
5   package com.qulice.pmd.rules;
6   
7   import net.sourceforge.pmd.lang.java.ast.ASTClassType;
8   import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
9   import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration;
10  
11  /**
12   * A supertype recognised by the name it is given in an {@code extends} or
13   * an {@code implements} clause. Qulice runs PMD without an auxiliary
14   * classpath, so a supertype that lives outside the file being analyzed
15   * never resolves to a type and only the name written in the clause is
16   * available. That name is trusted when it is fully qualified, or when the
17   * file imports the type, either directly or on demand from its package.
18   *
19   * @since 1.0
20   */
21  final class NamedSupertype {
22  
23      /**
24       * Canonical name of the type, e.g. {@code com.sun.jna.Library}.
25       */
26      private final String canonical;
27  
28      /**
29       * Constructor.
30       *
31       * @param name Canonical name of the type
32       */
33      NamedSupertype(final String name) {
34          this.canonical = name;
35      }
36  
37      /**
38       * Does the given clause name this very type?
39       *
40       * @param clause Type named in an extends or implements clause,
41       *  may be NULL when the clause is absent
42       * @return TRUE if the clause names this type
43       */
44      boolean matches(final ASTClassType clause) {
45          return clause != null
46              && this.simple().equals(clause.getSimpleName())
47              && (this.pack().equals(clause.getPackageQualifier())
48                  || this.imported(clause.getRoot()));
49      }
50  
51      private String simple() {
52          return this.canonical.substring(this.canonical.lastIndexOf('.') + 1);
53      }
54  
55      private String pack() {
56          return this.canonical.substring(0, this.canonical.lastIndexOf('.'));
57      }
58  
59      private boolean imported(final ASTCompilationUnit unit) {
60          return unit.children(ASTImportDeclaration.class).any(this::brings);
61      }
62  
63      private boolean brings(final ASTImportDeclaration imported) {
64          return this.canonical.equals(imported.getImportedName())
65              || imported.isImportOnDemand()
66              && this.pack().equals(imported.getImportedName());
67      }
68  }