mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
file templates: project-aware velocity context
This commit is contained in:
@@ -36,7 +36,7 @@ public class FileTemplatesTest extends IdeaTestCase {
|
||||
final File customInclude = new File(testsDir, customIncludeFileName);
|
||||
final String includeText = FileUtil.loadFile(customInclude, FileTemplate.ourEncoding);
|
||||
|
||||
final FileTemplateManager templateManager = FileTemplateManager.getDefaultInstance();
|
||||
final FileTemplateManager templateManager = FileTemplateManager.getInstance(getProject());
|
||||
final ArrayList<FileTemplate> originalIncludes = new ArrayList<FileTemplate>(Arrays.asList(templateManager.getAllPatterns()));
|
||||
try {
|
||||
// configure custom include
|
||||
@@ -67,9 +67,10 @@ public class FileTemplatesTest extends IdeaTestCase {
|
||||
EncodingAwareProperties properties = new EncodingAwareProperties();
|
||||
|
||||
properties.load(propFile, FileTemplate.ourEncoding);
|
||||
properties.put(FileTemplateManager.PROJECT_NAME_VARIABLE, getProject().getName())
|
||||
|
||||
System.out.println(resultFile.getName());
|
||||
doTestTemplate(inputText, properties, outputText, resultFile.getParent());
|
||||
doTestTemplate(inputText, properties, outputText);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
@@ -77,19 +78,19 @@ public class FileTemplatesTest extends IdeaTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
private static void doTestTemplate(String inputString, Properties properties, String expected, String dir) throws Exception {
|
||||
private void doTestTemplate(String inputString, Properties properties, String expected) throws Exception {
|
||||
inputString = StringUtil.convertLineSeparators(inputString);
|
||||
expected = StringUtil.convertLineSeparators(expected);
|
||||
|
||||
final String result = FileTemplateUtil.mergeTemplate(properties, inputString, false);
|
||||
assertEquals(expected, result);
|
||||
|
||||
List attrs = Arrays.asList(FileTemplateUtil.calculateAttributes(inputString, new Properties(), false));
|
||||
assertTrue(properties.size() <= attrs.size());
|
||||
List attrs = Arrays.asList(FileTemplateUtil.calculateAttributes(inputString, new Properties(), false, getProject()));
|
||||
assertTrue(properties.size() - 1 <= attrs.size());
|
||||
Enumeration e = properties.propertyNames();
|
||||
while (e.hasMoreElements()) {
|
||||
String s = (String)e.nextElement();
|
||||
assertTrue("Attribute '" + s + "' not found in properties", attrs.contains(s));
|
||||
assertTrue("Attribute '" + s + "' not found in properties", attrs.contains(s) || FileTemplateManager.PROJECT_NAME_VARIABLE.equals(s));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +103,7 @@ public class FileTemplatesTest extends IdeaTestCase {
|
||||
FileTemplate template = addTestTemplate("myclass", '${ABC} ${DEF} ${NAME}')
|
||||
Properties properties = new Properties()
|
||||
properties.NAME = 'zzz'
|
||||
assert template.getUnsetAttributes(properties) as Set == ['ABC', 'DEF'] as Set
|
||||
assert template.getUnsetAttributes(properties, project) as Set == ['ABC', 'DEF'] as Set
|
||||
}
|
||||
|
||||
public void "test collect undefined attribute names from included templates"() {
|
||||
@@ -112,7 +113,7 @@ public class FileTemplatesTest extends IdeaTestCase {
|
||||
FileTemplate template = addTestTemplate("myclass", '#parse("included.java") ${DEF} ${NAME}')
|
||||
Properties properties = new Properties()
|
||||
properties.NAME = 'zzz'
|
||||
assert template.getUnsetAttributes(properties) as Set == ['ABC', 'DEF'] as Set
|
||||
assert template.getUnsetAttributes(properties, project) as Set == ['ABC', 'DEF'] as Set
|
||||
}
|
||||
|
||||
public void testDefaultPackage() throws Exception {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.intellij.ide.fileTemplates;
|
||||
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import org.apache.velocity.runtime.parser.ParseException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -49,8 +50,6 @@ public interface FileTemplate extends Cloneable {
|
||||
String ATTRIBUTE_NAME = "NAME";
|
||||
String ATTRIBUTE_FILE_NAME = "FILE_NAME";
|
||||
|
||||
@NotNull String[] getUnsetAttributes(@NotNull Properties properties) throws ParseException;
|
||||
|
||||
/** Name without extension */
|
||||
@NotNull String getName();
|
||||
|
||||
@@ -83,4 +82,6 @@ public interface FileTemplate extends Cloneable {
|
||||
void setReformatCode(boolean reformat);
|
||||
|
||||
FileTemplate clone();
|
||||
|
||||
@NotNull String[] getUnsetAttributes(@NotNull Properties properties, Project project) throws ParseException;
|
||||
}
|
||||
|
||||
@@ -50,6 +50,8 @@ public abstract class FileTemplateManager{
|
||||
public static final String CODE_TEMPLATES_CATEGORY = "Code";
|
||||
public static final String J2EE_TEMPLATES_CATEGORY = "J2EE";
|
||||
|
||||
public static final String PROJECT_NAME_VARIABLE = "PROJECT_NAME";
|
||||
|
||||
public static FileTemplateManager getInstance(@NotNull Project project){
|
||||
return ServiceManager.getService(project, FileTemplateManager.class);
|
||||
}
|
||||
@@ -89,7 +91,7 @@ public abstract class FileTemplateManager{
|
||||
@NotNull
|
||||
public Properties getDefaultProperties(@NotNull Project project) {
|
||||
Properties properties = getDefaultProperties();
|
||||
properties.setProperty("PROJECT_NAME", project.getName());
|
||||
properties.setProperty(PROJECT_NAME_VARIABLE, project.getName());
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,12 +31,14 @@ import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.project.ex.ProjectManagerEx;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.ClassLoaderUtil;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.ThrowableComputable;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.apache.commons.collections.ExtendedProperties;
|
||||
import org.apache.velocity.VelocityContext;
|
||||
import org.apache.velocity.app.Velocity;
|
||||
@@ -66,6 +68,7 @@ import java.util.*;
|
||||
public class FileTemplateUtil{
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.fileTemplates.FileTemplateUtil");
|
||||
private static final CreateFromTemplateHandler ourDefaultCreateFromTemplateHandler = new DefaultCreateFromTemplateHandler();
|
||||
private static final ThreadLocal<FileTemplateManager> ourTemplateManager = new ThreadLocal<FileTemplateManager>();
|
||||
|
||||
@NonNls public static final String INTERNAL_PACKAGE_INFO_TEMPLATE_NAME = "package-info";
|
||||
|
||||
@@ -74,8 +77,6 @@ public class FileTemplateUtil{
|
||||
|
||||
static {
|
||||
try{
|
||||
final FileTemplateManager templateManager = FileTemplateManager.getInstance(ProjectManager.getInstance().getDefaultProject());
|
||||
|
||||
LogSystem emptyLogSystem = new LogSystem() {
|
||||
@Override
|
||||
public void init(RuntimeServices runtimeServices) throws Exception {
|
||||
@@ -97,6 +98,8 @@ public class FileTemplateUtil{
|
||||
|
||||
@Override
|
||||
public InputStream getResourceStream(String resourceName) throws ResourceNotFoundException {
|
||||
FileTemplateManager templateManager = ourTemplateManager.get();
|
||||
if (templateManager == null) templateManager = FileTemplateManager.getDefaultInstance();
|
||||
final FileTemplate include = templateManager.getPattern(resourceName);
|
||||
if (include == null) {
|
||||
throw new ResourceNotFoundException("Template not found: " + resourceName);
|
||||
@@ -127,36 +130,42 @@ public class FileTemplateUtil{
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] calculateAttributes(String templateContent, Properties properties, boolean includeDummies) throws ParseException {
|
||||
public static String[] calculateAttributes(String templateContent, Properties properties, boolean includeDummies, Project project) throws ParseException {
|
||||
Set<String> propertiesNames = new HashSet<String>();
|
||||
for (Enumeration e = properties.propertyNames(); e.hasMoreElements(); ) {
|
||||
propertiesNames.add((String)e.nextElement());
|
||||
}
|
||||
return calculateAttributes(templateContent, propertiesNames, includeDummies);
|
||||
return calculateAttributes(templateContent, propertiesNames, includeDummies, project);
|
||||
}
|
||||
|
||||
public static String[] calculateAttributes(String templateContent, Map<String, Object> properties, boolean includeDummies) throws ParseException {
|
||||
return calculateAttributes(templateContent, properties.keySet(), includeDummies);
|
||||
public static String[] calculateAttributes(String templateContent, Map<String, Object> properties, boolean includeDummies, Project project) throws ParseException {
|
||||
return calculateAttributes(templateContent, properties.keySet(), includeDummies, project);
|
||||
}
|
||||
|
||||
public static String[] calculateAttributes(String templateContent, Set<String> propertiesNames, boolean includeDummies) throws ParseException {
|
||||
private static String[] calculateAttributes(String templateContent, Set<String> propertiesNames, boolean includeDummies, Project project) throws ParseException {
|
||||
final Set<String> unsetAttributes = new LinkedHashSet<String>();
|
||||
final Set<String> definedAttributes = new HashSet<String>();
|
||||
//noinspection HardCodedStringLiteral
|
||||
SimpleNode template = RuntimeSingleton.parse(new StringReader(templateContent), "MyTemplate");
|
||||
collectAttributes(unsetAttributes, definedAttributes, template, propertiesNames, includeDummies, new HashSet<String>());
|
||||
collectAttributes(unsetAttributes, definedAttributes, template, propertiesNames, includeDummies, new HashSet<String>(), project);
|
||||
for (String definedAttribute : definedAttributes) {
|
||||
unsetAttributes.remove(definedAttribute);
|
||||
}
|
||||
return ArrayUtil.toStringArray(unsetAttributes);
|
||||
}
|
||||
|
||||
private static void collectAttributes(Set<String> referenced, Set<String> defined, Node apacheNode, final Set<String> propertiesNames, final boolean includeDummies, Set<String> visitedIncludes)
|
||||
private static void collectAttributes(Set<String> referenced,
|
||||
Set<String> defined,
|
||||
Node apacheNode,
|
||||
final Set<String> propertiesNames,
|
||||
final boolean includeDummies,
|
||||
Set<String> visitedIncludes,
|
||||
Project project)
|
||||
throws ParseException {
|
||||
int childCount = apacheNode.jjtGetNumChildren();
|
||||
for(int i = 0; i < childCount; i++){
|
||||
Node apacheChild = apacheNode.jjtGetChild(i);
|
||||
collectAttributes(referenced, defined, apacheChild, propertiesNames, includeDummies, visitedIncludes);
|
||||
collectAttributes(referenced, defined, apacheChild, propertiesNames, includeDummies, visitedIncludes, project);
|
||||
if (apacheChild instanceof ASTReference){
|
||||
ASTReference apacheReference = (ASTReference)apacheChild;
|
||||
String s = apacheReference.literal();
|
||||
@@ -178,10 +187,10 @@ public class FileTemplateUtil{
|
||||
Token firstToken = literal.getFirstToken();
|
||||
if (firstToken != null) {
|
||||
String s = StringUtil.unquoteString(firstToken.toString());
|
||||
final FileTemplate includedTemplate = FileTemplateManager.getDefaultInstance().getTemplate(s);
|
||||
final FileTemplate includedTemplate = FileTemplateManager.getInstance(project).getTemplate(s);
|
||||
if (includedTemplate != null && visitedIncludes.add(s)) {
|
||||
SimpleNode template = RuntimeSingleton.parse(new StringReader(includedTemplate.getText()), "MyTemplate");
|
||||
collectAttributes(referenced, defined, template, propertiesNames, includeDummies, visitedIncludes);
|
||||
collectAttributes(referenced, defined, template, propertiesNames, includeDummies, visitedIncludes, project);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -270,7 +279,24 @@ public class FileTemplateUtil{
|
||||
private static String mergeTemplate(String templateContent, final VelocityContext context, boolean useSystemLineSeparators) throws IOException {
|
||||
final StringWriter stringWriter = new StringWriter();
|
||||
try {
|
||||
Velocity.evaluate(context, stringWriter, "", templateContent);
|
||||
Project project = null;
|
||||
final Object projectName = context.get(FileTemplateManager.PROJECT_NAME_VARIABLE);
|
||||
if (projectName instanceof String) {
|
||||
Project[] projects = ProjectManager.getInstance().getOpenProjects();
|
||||
project = ContainerUtil.find(projects, new Condition<Project>() {
|
||||
@Override
|
||||
public boolean value(Project project) {
|
||||
return projectName.equals(project.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
try {
|
||||
ourTemplateManager.set(project == null ? FileTemplateManager.getDefaultInstance() : FileTemplateManager.getInstance(project));
|
||||
Velocity.evaluate(context, stringWriter, "", templateContent);
|
||||
}
|
||||
finally {
|
||||
ourTemplateManager.set(null);
|
||||
}
|
||||
}
|
||||
catch (final VelocityException e) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
@@ -356,7 +382,7 @@ public class FileTemplateUtil{
|
||||
}
|
||||
|
||||
//Set escaped references to dummy values to remove leading "\" (if not already explicitly set)
|
||||
String[] dummyRefs = calculateAttributes(template.getText(), propsMap, true);
|
||||
String[] dummyRefs = calculateAttributes(template.getText(), propsMap, true, directory.getProject());
|
||||
for (String dummyRef : dummyRefs) {
|
||||
propsMap.put(dummyRef, "");
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.intellij.ide.fileTemplates.FileTemplate;
|
||||
import com.intellij.ide.fileTemplates.FileTemplateUtil;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.ex.FileTypeManagerEx;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.apache.velocity.runtime.parser.ParseException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -94,8 +95,8 @@ public abstract class FileTemplateBase implements FileTemplate {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public final String[] getUnsetAttributes(@NotNull Properties properties) throws ParseException {
|
||||
return FileTemplateUtil.calculateAttributes(getText(), properties, false);
|
||||
public final String[] getUnsetAttributes(@NotNull Properties properties, Project project) throws ParseException {
|
||||
return FileTemplateUtil.calculateAttributes(getText(), properties, false, project);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -210,7 +210,7 @@ public class FileTemplateManagerImpl extends FileTemplateManager implements Pers
|
||||
|
||||
props.setProperty("DS", "$"); // Dollar sign, strongly needed for PHP, JS, etc. See WI-8979
|
||||
|
||||
props.setProperty("PROJECT_NAME", myProject.getName());
|
||||
props.setProperty(PROJECT_NAME_VARIABLE, myProject.getName());
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ public class CreateFromTemplateDialog extends DialogWrapper {
|
||||
|
||||
String[] unsetAttributes = null;
|
||||
try {
|
||||
unsetAttributes = myTemplate.getUnsetAttributes(myDefaultProperties);
|
||||
unsetAttributes = myTemplate.getUnsetAttributes(myDefaultProperties, project);
|
||||
}
|
||||
catch (ParseException e) {
|
||||
showErrorDialog(e);
|
||||
|
||||
Reference in New Issue
Block a user