1
2
3
4
5 package com.qulice.checkstyle;
6
7 import com.puppycrawl.tools.checkstyle.api.DetailAST;
8 import com.puppycrawl.tools.checkstyle.api.FullIdent;
9 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
10 import java.util.Collection;
11 import java.util.Set;
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 final class JnaBinding {
30
31
32
33
34
35 private static final Collection<String> LIBRARIES = Set.of(
36 "com.sun.jna.Library",
37 "com.sun.jna.win32.StdCallLibrary"
38 );
39
40
41
42
43 private final DetailAST node;
44
45
46
47
48
49
50 JnaBinding(final DetailAST method) {
51 this.node = method;
52 }
53
54
55
56
57
58
59 boolean is() {
60 DetailAST type = this.node.getParent();
61 boolean answer = false;
62 while (type != null) {
63 if (type.getType() == TokenTypes.CLASS_DEF
64 || type.getType() == TokenTypes.INTERFACE_DEF) {
65 answer = JnaBinding.mapped(type);
66 break;
67 }
68 type = type.getParent();
69 }
70 return answer;
71 }
72
73 private static boolean mapped(final DetailAST type) {
74 return JnaBinding.declares(type, TokenTypes.EXTENDS_CLAUSE)
75 || JnaBinding.declares(type, TokenTypes.IMPLEMENTS_CLAUSE);
76 }
77
78 private static boolean declares(final DetailAST type, final int clause) {
79 final DetailAST names = type.findFirstToken(clause);
80 final boolean answer;
81 if (names == null) {
82 answer = false;
83 } else {
84 answer = new ChildStream(names).children()
85 .anyMatch(JnaBinding::library);
86 }
87 return answer;
88 }
89
90 private static boolean library(final DetailAST name) {
91 final String text = FullIdent.createFullIdent(name).getText();
92 return JnaBinding.LIBRARIES.stream().anyMatch(
93 known -> known.equals(text)
94 || JnaBinding.simple(known).equals(text)
95 && JnaBinding.imported(name, known)
96 );
97 }
98
99 private static boolean imported(final DetailAST node, final String known) {
100 DetailAST root = node;
101 while (root.getParent() != null) {
102 root = root.getParent();
103 }
104 return new ChildStream(root).children().anyMatch(
105 child -> JnaBinding.importing(child, known)
106 );
107 }
108
109 private static boolean importing(final DetailAST node, final String known) {
110 return node.getType() == TokenTypes.IMPORT
111 && JnaBinding.brings(
112 FullIdent.createFullIdentBelow(node).getText(), known
113 );
114 }
115
116 private static boolean brings(final String text, final String known) {
117 return known.equals(text)
118 || String.format("%s.*", JnaBinding.pack(known)).equals(text);
119 }
120
121 private static String simple(final String known) {
122 return known.substring(known.lastIndexOf('.') + 1);
123 }
124
125 private static String pack(final String known) {
126 return known.substring(0, known.lastIndexOf('.'));
127 }
128 }