JaroslavTulach commented on a change in pull request #3076: URL: https://github.com/apache/netbeans/pull/3076#discussion_r678479698
########## File path: groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/compiler/ParsingCompilerCustomizer.java ########## @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.groovy.editor.compiler; + +import org.codehaus.groovy.control.CompilationUnit; +import org.codehaus.groovy.control.CompilerConfiguration; +import org.netbeans.modules.parsing.api.Snapshot; +import org.netbeans.modules.parsing.api.Task; +import org.netbeans.spi.editor.mimelookup.MimeLocation; + +/** + * Customizes the Groovy Compiler for parsing purposes. Implementations may add some processors, + * transformations or disable global library transformations, or revert their effects. + * + * Note: this is not yet an API class, but may become one when declarative registration (@link SimpleTransformationCustomizer} + * is not sufficient. + * + * @author sdedic + */ +@MimeLocation(subfolderName = "Parser") +public interface ParsingCompilerCustomizer { + + /** + * Decorates initial {@link CompilerConfig} before the {@link CompilationUnit} is created. Some initialization + * may happen early in the constructor, like fetching global transformations. The method may return a different instance + * of CompilerConfiguration. + * + * @param ctx parsing context + * @param cfg configuration to customize + * @return new configuration object + */ + public CompilerConfiguration configureParsingCompiler(Context ctx, CompilerConfiguration cfg); + + /** + * Decorates a compilation after the CompilationUnit is constructed and before the parsing is done. Transformers added here + * follow the standard ones. + * @param ctx parsing context + * @param cu compilation unit instance + * @return decorated compilation unit + */ + public void decorateCompilation(Context ctx, CompilationUnit cu); + + /** + * Context for the parsing task. + */ + public final class Context { + private final Snapshot snapshot; + private final Task consumerTask; + + /** + * Constructs the context. + * @param snap + * @param calerTask + */ + public Context(Snapshot snap, Task calerTask) { Review comment: Typo `callerTask` I guess. ########## File path: groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/compiler/ApplyGroovyTransformationProcessor.java ########## @@ -0,0 +1,120 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.groovy.editor.compiler; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import javax.annotation.processing.Processor; +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; +import org.codehaus.groovy.transform.ASTTransformation; +import org.netbeans.modules.groovy.editor.api.parser.ApplyGroovyTransformation; +import org.openide.filesystems.annotations.LayerBuilder.File; +import org.openide.filesystems.annotations.LayerGeneratingProcessor; +import org.openide.filesystems.annotations.LayerGenerationException; +import org.openide.util.lookup.ServiceProvider; + +/** + * + * @author sdedic + */ +@ServiceProvider(service=Processor.class) +public class ApplyGroovyTransformationProcessor extends LayerGeneratingProcessor { + private static final Set<String> APPLY_DEFAULT = new HashSet<>(Arrays.asList(new String[] { "parse" })); // NOI18N + + public @Override Set<String> getSupportedAnnotationTypes() { + return Collections.singleton(ApplyGroovyTransformation.class.getCanonicalName()); + } + + @Override + protected boolean handleProcess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) throws LayerGenerationException { + if (roundEnv.processingOver()) { + return false; + } + for (Element e : roundEnv.getElementsAnnotatedWith(ApplyGroovyTransformation.class)) { + ApplyGroovyTransformation agt = e.getAnnotation(ApplyGroovyTransformation.class); + String[] transformations = agt.value(); + Set<String> enableFor = new HashSet<>(Arrays.asList(agt.enable())); + Set<String> disableFor = new HashSet<>(Arrays.asList(agt.disable())); + + if (transformations.length == 0) { + TypeMirror astType = processingEnv.getElementUtils().getTypeElement(ASTTransformation.class.getName()).asType(); + if (!processingEnv.getTypeUtils().isAssignable(e.asType(), astType)) { + throw new LayerGenerationException("Element " + e + " is not subclass of " + astType + " and transformation class is not specified by the annotation.", e); //NOI18N + } + + String bn = processingEnv.getElementUtils().getBinaryName((TypeElement)e).toString(); + transformations = new String[] { bn }; + if (enableFor.isEmpty()) { + enableFor = APPLY_DEFAULT; + } + } else { + if (enableFor.isEmpty() && disableFor.isEmpty()) { + disableFor = APPLY_DEFAULT; + } + } + + for (String mt : agt.mimeTypes()) { + String fnbase = "Editors/" + mt + "/Parser"; // NOI18N + String en = null; + + if (e instanceof TypeElement) { + en = ((TypeElement)e).getQualifiedName().toString(); + } else if (e instanceof PackageElement) { + en = ((PackageElement)e).getQualifiedName().toString(); + } else { + throw new LayerGenerationException("Unexpected annotated element:" + e, e); //NOI18N + } + + File f = null; + if (!enableFor.isEmpty()) { + f = generateFile(f, e, fnbase, en, enableFor, "enable", transformations); // NOI18N + } + if (!disableFor.isEmpty()) { + f = generateFile(f, e, fnbase, en, disableFor, "disable", transformations); // NOI18N + } + if (f != null) { + f.write(); + } + } + } + return true; + } + + private File generateFile(File f, Element e, String fnbase, String en, Set<String> items, String att, String[] transformations) throws LayerGenerationException { + boolean simple = items.size() == 1 && items.contains(ApplyGroovyTransformation.APPLY_PARSE); + + if (f == null) { + f = layer(e).instanceFile(fnbase, en). + stringvalue("instanceOf", ParsingCompilerCustomizer.class.getName()). // NOI18N + methodvalue("instanceCreate", SimpleTransformationCustomizer.class.getName(), "fromLayer"); // NOI18N Review comment: The fully qualified name of `SimpleTransformationCustomizer` and its `fromLayer` method becomes an API that cannot be changed. It might be better to move the factory to some class that is already part of the API... ########## File path: groovy/groovy.editor/src/org/netbeans/modules/groovy/editor/api/parser/GroovyParser.java ########## @@ -126,18 +127,14 @@ public void parse(Snapshot snapshot, Task task, SourceModificationEvent event) t cancelled.set(false); if (!GroovyUtils.isIndexingEnabled()) { - // HACK: Indexing cannot be registered 'conditionally'. Once an indexer is registered for text/x-groovy, Review comment: Once hack less. Great! -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected] For further information about the NetBeans mailing lists, visit: https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists
