org.gradle.plugin.use.internal.PluginUseScriptBlockMetadataExtractor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-api Show documentation
Show all versions of gradle-api Show documentation
Gradle 6.9.1 API redistribution.
/*
* Copyright 2013 the original author or authors.
*
* Licensed 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.gradle.plugin.use.internal;
import org.codehaus.groovy.ast.expr.ClosureExpression;
import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.MethodCallExpression;
import org.codehaus.groovy.ast.stmt.BlockStatement;
import org.codehaus.groovy.ast.stmt.ExpressionStatement;
import org.codehaus.groovy.ast.stmt.Statement;
import org.codehaus.groovy.control.SourceUnit;
import org.gradle.api.internal.DocumentationRegistry;
import org.gradle.groovy.scripts.ScriptSource;
import org.gradle.groovy.scripts.internal.RestrictiveCodeVisitor;
import org.gradle.groovy.scripts.internal.ScriptBlock;
import org.gradle.plugin.internal.InvalidPluginIdException;
import org.gradle.plugin.management.internal.PluginRequests;
import org.gradle.plugin.use.PluginDependencySpec;
import static org.gradle.groovy.scripts.internal.AstUtils.hasSingleConstantArgOfType;
import static org.gradle.groovy.scripts.internal.AstUtils.isOfType;
public class PluginUseScriptBlockMetadataExtractor {
public static final String NEED_SINGLE_BOOLEAN = "argument list must be exactly 1 literal boolean";
public static final String NEED_SINGLE_STRING = "argument list must be exactly 1 literal non empty string";
public static final String BASE_MESSAGE = "only id(String) method calls allowed in plugins {} script block";
public static final String EXTENDED_MESSAGE = "only version(String) and apply(boolean) method calls allowed in plugins {} script block";
private static final String NOT_LITERAL_METHOD_NAME = "method name must be literal (i.e. not a variable)";
private static final String NOT_LITERAL_ID_METHOD_NAME = BASE_MESSAGE + " - " + NOT_LITERAL_METHOD_NAME;
private final DocumentationRegistry documentationRegistry;
private final PluginRequestCollector pluginRequestCollector;
public PluginUseScriptBlockMetadataExtractor(ScriptSource scriptSource, DocumentationRegistry documentationRegistry) {
this.pluginRequestCollector = new PluginRequestCollector(scriptSource);
this.documentationRegistry = documentationRegistry;
}
public void extract(SourceUnit sourceUnit, ScriptBlock scriptBlock) {
ClosureExpression closureArg = scriptBlock.getClosureExpression();
closureArg.getCode().visit(new RestrictiveCodeVisitor(sourceUnit, formatErrorMessage(BASE_MESSAGE)) {
@Override
public void visitBlockStatement(BlockStatement block) {
for (Statement statement : block.getStatements()) {
statement.visit(this);
}
}
@Override
public void visitMethodCallExpression(MethodCallExpression call) {
if (!call.isImplicitThis()) {
Expression target = call.getObjectExpression();
if (!(target instanceof MethodCallExpression)) {
restrict(target, formatErrorMessage(BASE_MESSAGE));
return;
}
visitMethodCallExpression((MethodCallExpression) target);
}
if (call.getMethod() instanceof ConstantExpression) {
ConstantExpression methodName = (ConstantExpression) call.getMethod();
if (isOfType(methodName, String.class)) {
String methodNameText = methodName.getText();
if (methodNameText.equals("id") || methodNameText.equals("version")) {
ConstantExpression argumentExpression = hasSingleConstantArgOfType(call, String.class);
if (argumentExpression == null) {
restrict(call, formatErrorMessage(NEED_SINGLE_STRING));
return;
}
String argStringValue = argumentExpression.getValue().toString();
if (argStringValue.length() == 0) {
restrict(argumentExpression, formatErrorMessage(NEED_SINGLE_STRING));
return;
}
if (methodName.getText().equals("id")) {
if (call.isImplicitThis()) {
try {
DefaultPluginId.validate(argStringValue);
call.setNodeMetaData(PluginDependencySpec.class, pluginRequestCollector.createSpec(call.getLineNumber()).id(argStringValue));
} catch (InvalidPluginIdException e) {
restrict(argumentExpression, formatErrorMessage(e.getReason()));
}
} else {
restrict(call, formatErrorMessage(BASE_MESSAGE));
}
}
if (methodName.getText().equals("version")) {
PluginDependencySpec spec = getSpecFor(call);
if (spec == null) {
return;
}
spec.version(argStringValue);
call.setNodeMetaData(PluginDependencySpec.class, spec);
}
} else if (methodNameText.equals("apply")) {
ConstantExpression arguments = hasSingleConstantArgOfType(call, boolean.class);
if (arguments == null) {
restrict(call, formatErrorMessage(NEED_SINGLE_BOOLEAN));
return;
}
PluginDependencySpec spec = getSpecFor(call);
if (spec == null) {
return;
}
spec.apply((Boolean) arguments.getValue());
} else {
if (!call.isImplicitThis()) {
restrict(methodName, formatErrorMessage(EXTENDED_MESSAGE));
} else {
restrict(methodName, formatErrorMessage(BASE_MESSAGE));
}
}
} else {
restrict(methodName, formatErrorMessage(NOT_LITERAL_ID_METHOD_NAME));
}
} else {
restrict(call);
}
}
private PluginDependencySpec getSpecFor(MethodCallExpression call) {
Expression objectExpression = call.getObjectExpression();
if (objectExpression instanceof MethodCallExpression) {
return objectExpression.getNodeMetaData(PluginDependencySpec.class);
} else {
restrict(call, formatErrorMessage(BASE_MESSAGE));
return null;
}
}
@Override
public void visitExpressionStatement(ExpressionStatement statement) {
statement.getExpression().visit(this);
}
});
}
public PluginRequests getPluginRequests() {
return pluginRequestCollector.getPluginRequests();
}
public String formatErrorMessage(String message) {
return String.format("%s%n%nSee %s for information on the plugins {} block%n%n", message, documentationRegistry.getDocumentationFor("plugins", "sec:plugins_block"));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy