comparison truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java @ 21951:9c8c0937da41

Moving all sources into truffle subdirectory
author Jaroslav Tulach <jaroslav.tulach@oracle.com>
date Wed, 17 Jun 2015 10:58:08 +0200
parents graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java@45083be8a812
children f878f9778548
comparison
equal deleted inserted replaced
21950:2a5011c7e641 21951:9c8c0937da41
1 /*
2 * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package com.oracle.truffle.dsl.processor;
24
25 import java.io.*;
26 import java.util.*;
27
28 import javax.annotation.processing.*;
29 import javax.lang.model.*;
30 import javax.lang.model.element.*;
31 import javax.lang.model.type.*;
32 import javax.tools.Diagnostic.Kind;
33 import javax.tools.*;
34
35 import com.oracle.truffle.api.*;
36 import com.oracle.truffle.api.TruffleLanguage.Registration;
37
38 @SupportedAnnotationTypes("com.oracle.truffle.api.*")
39 public final class LanguageRegistrationProcessor extends AbstractProcessor {
40 private final List<TypeElement> registrations = new ArrayList<>();
41
42 @Override
43 public SourceVersion getSupportedSourceVersion() {
44 return SourceVersion.latest();
45 }
46
47 private void generateFile(List<TypeElement> languages) {
48 String filename = "META-INF/truffle/language";
49 Properties p = new Properties();
50 int cnt = 0;
51 for (TypeElement l : languages) {
52 Registration annotation = l.getAnnotation(Registration.class);
53 if (annotation == null) {
54 continue;
55 }
56 String prefix = "language" + ++cnt + ".";
57 String className = processingEnv.getElementUtils().getBinaryName(l).toString();
58 p.setProperty(prefix + "name", annotation.name());
59 p.setProperty(prefix + "version", annotation.version());
60 p.setProperty(prefix + "className", className);
61 String[] mimes = annotation.mimeType();
62 for (int i = 0; i < mimes.length; i++) {
63 p.setProperty(prefix + "mimeType." + i, mimes[i]);
64 }
65 }
66 if (cnt > 0) {
67 try {
68 FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, languages.toArray(new Element[0]));
69 try (OutputStream os = file.openOutputStream()) {
70 p.store(os, "Generated by " + LanguageRegistrationProcessor.class.getName());
71 }
72 } catch (IOException e) {
73 processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), languages.get(0));
74 }
75 }
76 }
77
78 @Override
79 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
80 if (roundEnv.processingOver()) {
81 generateFile(registrations);
82 registrations.clear();
83 return true;
84 }
85 for (Element e : roundEnv.getElementsAnnotatedWith(Registration.class)) {
86 Registration annotation = e.getAnnotation(Registration.class);
87 if (annotation != null && e.getKind() == ElementKind.CLASS) {
88 if (!e.getModifiers().contains(Modifier.PUBLIC)) {
89 emitError("Registered language class must be public", e);
90 continue;
91 }
92 if (e.getEnclosingElement().getKind() != ElementKind.PACKAGE && !e.getModifiers().contains(Modifier.STATIC)) {
93 emitError("Registered language inner-class must be static", e);
94 continue;
95 }
96 TypeMirror truffleLang = processingEnv.getElementUtils().getTypeElement(TruffleLanguage.class.getName()).asType();
97 if (!processingEnv.getTypeUtils().isAssignable(e.asType(), truffleLang)) {
98 emitError("Registered language class must subclass TruffleLanguage", e);
99 continue;
100 }
101 boolean found = false;
102 for (Element mem : e.getEnclosedElements()) {
103 if (mem.getKind() != ElementKind.CONSTRUCTOR) {
104 continue;
105 }
106 ExecutableElement ee = (ExecutableElement) mem;
107 if (ee.getParameters().size() != 1) {
108 continue;
109 }
110 if (!ee.getModifiers().contains(Modifier.PUBLIC)) {
111 continue;
112 }
113 TypeMirror env = processingEnv.getElementUtils().getTypeElement(TruffleLanguage.Env.class.getCanonicalName()).asType();
114 if (processingEnv.getTypeUtils().isSameType(ee.getParameters().get(0).asType(), env)) {
115 found = true;
116 break;
117 }
118 }
119 if (!found) {
120 emitError("Language must have a public constructor accepting TruffleLanguage.Env as parameter", e);
121 continue;
122 }
123 assertNoErrorExpected(e);
124 registrations.add((TypeElement) e);
125 }
126 }
127
128 return true;
129 }
130
131 void assertNoErrorExpected(Element e) {
132 ExpectError.assertNoErrorExpected(processingEnv, e);
133 }
134
135 void emitError(String msg, Element e) {
136 if (ExpectError.isExpectedError(processingEnv, e, msg)) {
137 return;
138 }
139 processingEnv.getMessager().printMessage(Kind.ERROR, msg, e);
140 }
141
142 }