Lines 39-44
Link Here
|
39 |
|
39 |
|
40 |
package org.netbeans.modules.projectapi; |
40 |
package org.netbeans.modules.projectapi; |
41 |
|
41 |
|
|
|
42 |
import java.util.List; |
42 |
import java.util.Set; |
43 |
import java.util.Set; |
43 |
import javax.annotation.processing.Processor; |
44 |
import javax.annotation.processing.Processor; |
44 |
import javax.annotation.processing.RoundEnvironment; |
45 |
import javax.annotation.processing.RoundEnvironment; |
Lines 46-55
Link Here
|
46 |
import javax.annotation.processing.SupportedSourceVersion; |
47 |
import javax.annotation.processing.SupportedSourceVersion; |
47 |
import javax.lang.model.SourceVersion; |
48 |
import javax.lang.model.SourceVersion; |
48 |
import javax.lang.model.element.Element; |
49 |
import javax.lang.model.element.Element; |
|
|
50 |
import javax.lang.model.element.ExecutableElement; |
51 |
import javax.lang.model.element.Modifier; |
49 |
import javax.lang.model.element.TypeElement; |
52 |
import javax.lang.model.element.TypeElement; |
|
|
53 |
import javax.lang.model.element.VariableElement; |
54 |
import javax.lang.model.type.DeclaredType; |
55 |
import javax.lang.model.type.MirroredTypeException; |
56 |
import javax.lang.model.type.TypeMirror; |
57 |
import javax.lang.model.util.ElementFilter; |
58 |
import org.netbeans.api.project.Project; |
59 |
import org.netbeans.spi.project.LookupMerger; |
50 |
import org.netbeans.spi.project.LookupProvider; |
60 |
import org.netbeans.spi.project.LookupProvider; |
|
|
61 |
import org.netbeans.spi.project.ProjectServiceProvider; |
51 |
import org.openide.filesystems.annotations.LayerGeneratingProcessor; |
62 |
import org.openide.filesystems.annotations.LayerGeneratingProcessor; |
52 |
import org.openide.filesystems.annotations.LayerGenerationException; |
63 |
import org.openide.filesystems.annotations.LayerGenerationException; |
|
|
64 |
import org.openide.util.Lookup; |
53 |
import org.openide.util.lookup.ServiceProvider; |
65 |
import org.openide.util.lookup.ServiceProvider; |
54 |
|
66 |
|
55 |
/** |
67 |
/** |
Lines 58-64
Link Here
|
58 |
*/ |
70 |
*/ |
59 |
@ServiceProvider(service=Processor.class) |
71 |
@ServiceProvider(service=Processor.class) |
60 |
@SupportedSourceVersion(SourceVersion.RELEASE_6) |
72 |
@SupportedSourceVersion(SourceVersion.RELEASE_6) |
61 |
@SupportedAnnotationTypes("org.netbeans.spi.project.LookupProvider.Registration") |
73 |
@SupportedAnnotationTypes({ |
|
|
74 |
"org.netbeans.spi.project.LookupProvider.Registration", |
75 |
"org.netbeans.spi.project.ProjectServiceProvider", |
76 |
"org.netbeans.spi.project.LookupMerger.Registration" |
77 |
}) |
62 |
public class LookupProviderAnnotationProcessor extends LayerGeneratingProcessor { |
78 |
public class LookupProviderAnnotationProcessor extends LayerGeneratingProcessor { |
63 |
|
79 |
|
64 |
@Override |
80 |
@Override |
Lines 72-78
Link Here
|
72 |
layer(e).instanceFile("Projects/" + type + "/Lookup", null, LookupProvider.class).write(); |
88 |
layer(e).instanceFile("Projects/" + type + "/Lookup", null, LookupProvider.class).write(); |
73 |
} |
89 |
} |
74 |
} |
90 |
} |
|
|
91 |
for (Element e : roundEnv.getElementsAnnotatedWith(ProjectServiceProvider.class)) { |
92 |
ProjectServiceProvider psp = e.getAnnotation(ProjectServiceProvider.class); |
93 |
TypeElement clazz = (TypeElement) e; |
94 |
TypeMirror service; |
95 |
try { |
96 |
psp.service(); |
97 |
assert false; |
98 |
continue; |
99 |
} catch (MirroredTypeException x) { |
100 |
service = x.getTypeMirror(); |
101 |
} |
102 |
if (!processingEnv.getTypeUtils().isAssignable(clazz.asType(), service)) { |
103 |
throw new LayerGenerationException("Not assignable to " + service, e); |
104 |
} |
105 |
int constructorCount = 0; |
106 |
CONSTRUCTOR: for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) { |
107 |
if (!constructor.getModifiers().contains(Modifier.PUBLIC)) { |
108 |
continue; |
109 |
} |
110 |
List<? extends VariableElement> params = constructor.getParameters(); |
111 |
if (params.size() > 2) { |
112 |
continue; |
113 |
} |
114 |
for (VariableElement param : params) { |
115 |
if (!param.asType().equals(processingEnv.getElementUtils().getTypeElement(Project.class.getCanonicalName()).asType()) && |
116 |
!param.asType().equals(processingEnv.getElementUtils().getTypeElement(Lookup.class.getCanonicalName()).asType())) { |
117 |
continue CONSTRUCTOR; |
118 |
} |
119 |
} |
120 |
constructorCount++; |
121 |
} |
122 |
if (constructorCount != 1) { |
123 |
throw new LayerGenerationException("Must have exactly one public constructor optionally taking Project and/or Lookup", e); |
124 |
} |
125 |
String binName = processingEnv.getElementUtils().getBinaryName(clazz).toString(); |
126 |
String serviceBinName = processingEnv.getElementUtils().getBinaryName((TypeElement) processingEnv.getTypeUtils().asElement(service)).toString(); |
127 |
if (serviceBinName.equals(LookupMerger.class.getName())) { |
128 |
throw new LayerGenerationException("@ProjectServiceProvider should not be used on LookupMerger; use @LookupMerger.Registration instead", e); |
129 |
} |
130 |
for (String type : psp.projectType()) { |
131 |
layer(e).file("Projects/" + type + "/Lookup/" + binName.replace('.', '-') + ".instance"). |
132 |
methodvalue("instanceCreate", LazyLookupProviders.class.getName(), "forProjectServiceProvider"). |
133 |
stringvalue("class", binName). |
134 |
stringvalue("service", serviceBinName). |
135 |
write(); |
136 |
} |
137 |
} |
138 |
for (Element e : roundEnv.getElementsAnnotatedWith(LookupMerger.Registration.class)) { |
139 |
LookupMerger.Registration lmr = e.getAnnotation(LookupMerger.Registration.class); |
140 |
TypeElement clazz = (TypeElement) e; |
141 |
String binName = processingEnv.getElementUtils().getBinaryName(clazz).toString(); |
142 |
DeclaredType service = findLookupMergerType((DeclaredType) clazz.asType()); |
143 |
if (service == null) { |
144 |
throw new LayerGenerationException("Not assignable to LookupMerger<T> for some T", e); |
145 |
} |
146 |
String serviceBinName = processingEnv.getElementUtils().getBinaryName((TypeElement) service.asElement()).toString(); |
147 |
for (String type : lmr.projectType()) { |
148 |
layer(e).file("Projects/" + type + "/Lookup/" + binName.replace('.', '-') + ".instance"). |
149 |
methodvalue("instanceCreate", LazyLookupProviders.class.getName(), "forLookupMerger"). |
150 |
// XXX if supporting also factory methods, could use instanceAttribute here so that attr value is actually a LookupMerger |
151 |
stringvalue("class", binName). |
152 |
stringvalue("service", serviceBinName). |
153 |
write(); |
154 |
} |
155 |
} |
75 |
return true; |
156 |
return true; |
76 |
} |
157 |
} |
77 |
|
158 |
|
|
|
159 |
private DeclaredType findLookupMergerType(DeclaredType t) { |
160 |
String rawName = processingEnv.getTypeUtils().erasure(t).toString(); |
161 |
if (rawName.equals(LookupMerger.class.getName())) { |
162 |
List<? extends TypeMirror> args = t.getTypeArguments(); |
163 |
if (args.size() == 1) { |
164 |
return (DeclaredType) args.get(0); |
165 |
} else { |
166 |
return null; |
167 |
} |
168 |
} |
169 |
for (TypeMirror supe : processingEnv.getTypeUtils().directSupertypes(t)) { |
170 |
DeclaredType result = findLookupMergerType((DeclaredType) supe); |
171 |
if (result != null) { |
172 |
return result; |
173 |
} |
174 |
} |
175 |
return null; |
176 |
} |
177 |
|
78 |
} |
178 |
} |