diff --git a/core/org.eclipse.cdt.ui/.settings/.api_filters b/core/org.eclipse.cdt.ui/.settings/.api_filters new file mode 100644 index 00000000000..d75b37633f2 --- /dev/null +++ b/core/org.eclipse.cdt.ui/.settings/.api_filters @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/codemanipulation/StubUtility.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/codemanipulation/StubUtility.java index b7333b61081..d53a69d6ff0 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/codemanipulation/StubUtility.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/codemanipulation/StubUtility.java @@ -9,6 +9,7 @@ * Rational Software - initial implementation * Anton Leherbauer (Wind River Systems) * Jens Elmenthaler (Verigy) - http://bugs.eclipse.org/235586 + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.corext.codemanipulation; @@ -24,7 +25,6 @@ import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ProjectScope; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.preferences.IScopeContext; @@ -67,7 +67,7 @@ import org.eclipse.cdt.internal.corext.util.Strings; import org.eclipse.cdt.internal.ui.viewsupport.ProjectTemplateStore; public class StubUtility { - private static final String[] EMPTY= new String[0]; + private static final String[] EMPTY= {}; private StubUtility() { } @@ -76,57 +76,110 @@ public class StubUtility { * Don't use this method directly, use CodeGeneration. * @see org.eclipse.cdt.ui.CodeGeneration#getHeaderFileContent(ITranslationUnit, String, String, String) */ - public static String getHeaderFileContent(ITranslationUnit tu, String fileComment, String typeComment, String declarations, String lineDelimiter) throws CoreException { - return getHeaderFileContent(getDefaultFileTemplate(tu), tu, fileComment, typeComment, declarations, lineDelimiter); + public static String getHeaderFileContent(ITranslationUnit tu, String declarations, + String fileComment, String includes, String namespaceBegin, String namespaceEnd, + String namespaceName, String typeComment, String typeName, + String lineDelimiter) throws CoreException { + return getHeaderFileContent(getDefaultFileTemplate(tu), tu, declarations, fileComment, + includes, namespaceBegin, namespaceEnd, namespaceName, typeComment, typeName, + lineDelimiter); } /* * Don't use this method directly, use CodeGeneration. * @see org.eclipse.cdt.ui.CodeGeneration#getHeaderFileContent(Template, ITranslationUnit, String, String, String) */ - public static String getHeaderFileContent(Template template, ITranslationUnit tu, String fileComment, String typeComment, String declarations, String lineDelimiter) throws CoreException { + public static String getHeaderFileContent(Template template, ITranslationUnit tu, + String declarations, String fileComment, String includes, String namespaceBegin, + String namespaceEnd, String namespaceName, String typeComment, String typeName, + String lineDelimiter) throws CoreException { if (template == null) { return null; } ICProject project= tu.getCProject(); CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), project, lineDelimiter); context.setTranslationUnitVariables(tu); - context.setVariable(CodeTemplateContextType.TYPE_COMMENT, typeComment != null ? typeComment : ""); //$NON-NLS-1$ - context.setVariable(CodeTemplateContextType.FILE_COMMENT, fileComment != null ? fileComment : ""); //$NON-NLS-1$ - context.setVariable(CodeTemplateContextType.DECLARATIONS, declarations != null ? declarations : ""); //$NON-NLS-1$ - context.setVariable(CodeTemplateContextType.TYPENAME, new Path(tu.getElementName()).removeFileExtension().toString()); String includeGuardSymbol= generateIncludeGuardSymbol(tu.getResource(), project); + context.setVariable(CodeTemplateContextType.DECLARATIONS, declarations != null ? declarations : ""); //$NON-NLS-1$ + context.setVariable(CodeTemplateContextType.FILE_COMMENT, fileComment != null ? fileComment : ""); //$NON-NLS-1$ context.setVariable(CodeTemplateContextType.INCLUDE_GUARD_SYMBOL, includeGuardSymbol != null ? includeGuardSymbol : ""); //$NON-NLS-1$ - - String[] fullLine= { CodeTemplateContextType.FILE_COMMENT, CodeTemplateContextType.TYPE_COMMENT, CodeTemplateContextType.DECLARATIONS }; - return evaluateTemplate(context, template, fullLine); + context.setVariable(CodeTemplateContextType.INCLUDES, includes != null ? includes : ""); //$NON-NLS-1$ + context.setVariable(CodeTemplateContextType.NAMESPACE_BEGIN, namespaceBegin != null ? namespaceBegin : ""); //$NON-NLS-1$ + context.setVariable(CodeTemplateContextType.NAMESPACE_END, namespaceEnd != null ? namespaceEnd : ""); //$NON-NLS-1$ + context.setVariable(CodeTemplateContextType.NAMESPACE_NAME, namespaceName != null ? namespaceName : ""); //$NON-NLS-1$ + context.setVariable(CodeTemplateContextType.TYPE_COMMENT, typeComment != null ? typeComment : ""); //$NON-NLS-1$ + context.setVariable(CodeTemplateContextType.TYPENAME, typeName != null ? typeName : ""); //$NON-NLS-1$ + String[] fullLine= { + CodeTemplateContextType.DECLARATIONS, CodeTemplateContextType.FILE_COMMENT, + CodeTemplateContextType.INCLUDES, + CodeTemplateContextType.NAMESPACE_BEGIN, CodeTemplateContextType.NAMESPACE_END, + CodeTemplateContextType.TYPE_COMMENT + }; + + String text = evaluateTemplate(context, template, fullLine); + if (!text.endsWith(lineDelimiter)) + text += lineDelimiter; + return text; } /* * Don't use this method directly, use CodeGeneration. - * @see org.eclipse.cdt.ui.CodeGeneration#getBodyFileContent(ITranslationUnit, String, String, String) + * @see org.eclipse.cdt.ui.CodeGeneration#getBodyFileContent(ITranslationUnit, String, String, String, String, String, String, String, String, String) */ - public static String getBodyFileContent(ITranslationUnit tu, String fileComment, String typeComment, String declarations, String lineDelimiter) throws CoreException { - return getBodyFileContent(getDefaultFileTemplate(tu), tu, fileComment, typeComment, declarations, lineDelimiter); + public static String getBodyFileContent(ITranslationUnit tu, + String declarations, String fileComment, String includes, String namespaceBegin, + String namespaceEnd, String namespaceName, String typeComment, String typeName, + String lineDelimiter) throws CoreException { + return getBodyFileContent(getDefaultFileTemplate(tu), tu, declarations, fileComment, + includes, namespaceBegin, namespaceEnd, namespaceName, typeComment, typeName, + lineDelimiter); } /* * Don't use this method directly, use CodeGeneration. - * @see org.eclipse.cdt.ui.CodeGeneration#getBodyFileContent(Template, ITranslationUnit, String, String, String) + * @see org.eclipse.cdt.ui.CodeGeneration#getBodyFileContent(Template, ITranslationUnit, String, String, String, String, String, String, String, String, String) */ - public static String getBodyFileContent(Template template, ITranslationUnit tu, String fileComment, String typeComment, String declarations, String lineDelimiter) throws CoreException { + public static String getBodyFileContent(Template template, ITranslationUnit tu, + String declarations, String fileComment, String includes, String namespaceBegin, + String namespaceEnd, String namespaceName, String typeComment, String typeName, + String lineDelimiter) throws CoreException { if (template == null) { return null; } ICProject project= tu.getCProject(); CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), project, lineDelimiter); context.setTranslationUnitVariables(tu); - context.setVariable(CodeTemplateContextType.TYPE_COMMENT, typeComment != null ? typeComment : ""); //$NON-NLS-1$ - context.setVariable(CodeTemplateContextType.FILE_COMMENT, fileComment != null ? fileComment : ""); //$NON-NLS-1$ context.setVariable(CodeTemplateContextType.DECLARATIONS, declarations != null ? declarations : ""); //$NON-NLS-1$ - - String[] fullLine= { CodeTemplateContextType.FILE_COMMENT, CodeTemplateContextType.TYPE_COMMENT, CodeTemplateContextType.DECLARATIONS }; - return evaluateTemplate(context, template, fullLine); + context.setVariable(CodeTemplateContextType.FILE_COMMENT, fileComment != null ? fileComment : ""); //$NON-NLS-1$ + context.setVariable(CodeTemplateContextType.INCLUDES, includes != null ? includes : ""); //$NON-NLS-1$ + context.setVariable(CodeTemplateContextType.NAMESPACE_BEGIN, namespaceBegin != null ? namespaceBegin : ""); //$NON-NLS-1$ + context.setVariable(CodeTemplateContextType.NAMESPACE_END, namespaceEnd != null ? namespaceEnd : ""); //$NON-NLS-1$ + context.setVariable(CodeTemplateContextType.NAMESPACE_NAME, namespaceName != null ? namespaceName : ""); //$NON-NLS-1$ + context.setVariable(CodeTemplateContextType.TYPE_COMMENT, typeComment != null ? typeComment : ""); //$NON-NLS-1$ + context.setVariable(CodeTemplateContextType.TYPENAME, typeName != null ? typeName : ""); //$NON-NLS-1$ + String[] fullLine= { + CodeTemplateContextType.DECLARATIONS, CodeTemplateContextType.FILE_COMMENT, + CodeTemplateContextType.INCLUDES, + CodeTemplateContextType.NAMESPACE_BEGIN, CodeTemplateContextType.NAMESPACE_END, + CodeTemplateContextType.TYPE_COMMENT + }; + String text = evaluateTemplate(context, template, fullLine); + if (!text.endsWith(lineDelimiter)) + text += lineDelimiter; + return text; + } + + /* + * Don't use this method directly, use CodeGeneration. + * @see org.eclipse.cdt.ui.CodeGeneration#getTestFileContent(ITranslationUnit, String, String, String) + */ + public static String getTestFileContent(ITranslationUnit tu, String declarations, + String fileComment, String includes, String namespaceBegin, String namespaceEnd, + String namespaceName, String typeName, String lineDelimiter) + throws CoreException { + return getBodyFileContent(getTestFileTemplate(tu), tu, declarations, fileComment, + includes, namespaceBegin, namespaceEnd, namespaceName, null, typeName, + lineDelimiter); } public static String getFileContent(Template template, IFile file, String lineDelimiter) throws CoreException { @@ -147,7 +200,31 @@ public class StubUtility { context.setVariable(CodeTemplateContextType.INCLUDE_GUARD_SYMBOL, includeGuardSymbol != null ? includeGuardSymbol : ""); //$NON-NLS-1$ context.setResourceVariables(file); String[] fullLine= { CodeTemplateContextType.FILE_COMMENT }; - return evaluateTemplate(context, template, fullLine); + + String text = evaluateTemplate(context, template, fullLine); + if (!text.endsWith(lineDelimiter)) + text += lineDelimiter; + return text; + } + + /* + * Don't use this method directly, use CodeGeneration. + */ + public static String getClassBodyContent(ICProject project, String className, + String classMemberDeclarations, String lineDelimiter) throws CoreException { + Template template= getCodeTemplate(CodeTemplateContextType.CLASS_BODY_ID, project); + if (template == null) { + return classMemberDeclarations; + } + CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), project, lineDelimiter); + context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE, className); + context.setVariable(CodeTemplateContextType.DECLARATIONS, classMemberDeclarations != null ? classMemberDeclarations : ""); //$NON-NLS-1$ + String str= evaluateTemplate(context, template, + new String[] { CodeTemplateContextType.DECLARATIONS }); + if (str == null && classMemberDeclarations != null && !Strings.containsOnlyWhitespaces(classMemberDeclarations)) { + return classMemberDeclarations; + } + return str; } /* @@ -158,6 +235,26 @@ public class StubUtility { return getMethodBodyContent(templateId, project, typeName, methodName, bodyStatement, lineDelimiter); } + /* + * Don't use this method directly, use CodeGeneration. + */ + public static String getMethodBodyContent(String templateId, ICProject project, String typeName, + String methodName, String bodyStatement, String lineDelimiter) throws CoreException { + Template template= getCodeTemplate(templateId, project); + if (template == null) { + return bodyStatement; + } + CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), project, lineDelimiter); + context.setVariable(CodeTemplateContextType.ENCLOSING_METHOD, methodName); + context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE, typeName); + context.setVariable(CodeTemplateContextType.BODY_STATEMENT, bodyStatement != null ? bodyStatement : ""); //$NON-NLS-1$ + String str= evaluateTemplate(context, template, new String[] { CodeTemplateContextType.BODY_STATEMENT }); + if (str == null && bodyStatement != null && !Strings.containsOnlyWhitespaces(bodyStatement)) { + return bodyStatement; + } + return str; + } + /* * Don't use this method directly, use CodeGeneration. */ @@ -177,20 +274,29 @@ public class StubUtility { /* * Don't use this method directly, use CodeGeneration. */ - public static String getMethodBodyContent(String templateId, ICProject project, String typeName, String methodName, String bodyStatement, String lineDelimiter) throws CoreException { - Template template= getCodeTemplate(templateId, project); + public static String getNamespaceBeginContent(ICProject project, String namespaceName, + String lineDelimiter) throws CoreException { + Template template= getCodeTemplate(CodeTemplateContextType.NAMESPACE_BEGIN_ID, project); if (template == null) { - return bodyStatement; + return null; } CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), project, lineDelimiter); - context.setVariable(CodeTemplateContextType.ENCLOSING_METHOD, methodName); - context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE, typeName); - context.setVariable(CodeTemplateContextType.BODY_STATEMENT, bodyStatement != null ? bodyStatement : ""); //$NON-NLS-1$ - String str= evaluateTemplate(context, template, new String[] { CodeTemplateContextType.BODY_STATEMENT }); - if (str == null && bodyStatement != null && !Strings.containsOnlyWhitespaces(bodyStatement)) { - return bodyStatement; + context.setVariable(CodeTemplateContextType.NAMESPACE_NAME, namespaceName); + return evaluateTemplate(context, template, EMPTY); + } + + /* + * Don't use this method directly, use CodeGeneration. + */ + public static String getNamespaceEndContent(ICProject project, String namespaceName, + String lineDelimiter) throws CoreException { + Template template= getCodeTemplate(CodeTemplateContextType.NAMESPACE_END_ID, project); + if (template == null) { + return null; } - return str; + CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), project, lineDelimiter); + context.setVariable(CodeTemplateContextType.NAMESPACE_NAME, namespaceName); + return evaluateTemplate(context, template, EMPTY); } /* @@ -512,6 +618,14 @@ public class StubUtility { return getCodeTemplate(templateId, tu.getCProject()); } + private static Template getTestFileTemplate(ITranslationUnit tu) { + String templateId= null; + if (tu.isCXXLanguage() && !tu.isHeaderUnit()) { + templateId= CodeTemplateContextType.CPP_TESTFILE_ID; + } + return getCodeTemplate(templateId, tu.getCProject()); + } + private static Template getCodeTemplate(String id, ICProject cProject) { return getCodeTemplate(id, cProject != null ? cProject.getProject() : null); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CodeTemplateContextType.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CodeTemplateContextType.java index 5ca6fe3864c..2d1270cb151 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CodeTemplateContextType.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CodeTemplateContextType.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Anton Leherbauer (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.corext.template.c; @@ -22,7 +23,7 @@ import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.internal.corext.codemanipulation.StubUtility; public class CodeTemplateContextType extends FileTemplateContextType { - /* context types */ + /* Context types */ private static final String CONTEXTTYPE_PREFIX= "org.eclipse.cdt.ui.text.codetemplates."; //$NON-NLS-1$ public static final String CPPSOURCEFILE_CONTEXTTYPE= CCorePlugin.CONTENT_TYPE_CXXSOURCE + FileTemplateContextType.CONTEXTTYPE_SUFFIX; @@ -31,9 +32,11 @@ public class CodeTemplateContextType extends FileTemplateContextType { public static final String CHEADERFILE_CONTEXTTYPE= CCorePlugin.CONTENT_TYPE_CHEADER + FileTemplateContextType.CONTEXTTYPE_SUFFIX; public static final String ASMSOURCEFILE_CONTEXTTYPE= CCorePlugin.CONTENT_TYPE_ASMSOURCE + FileTemplateContextType.CONTEXTTYPE_SUFFIX; - public static final String METHODBODY_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "methodbody_context"; //$NON-NLS-1$ + public static final String NAMESPACE_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "namespace_context"; //$NON-NLS-1$ + public static final String CLASS_BODY_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "class_context"; //$NON-NLS-1$ public static final String CONSTRUCTORBODY_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "constructorbody_context"; //$NON-NLS-1$ public static final String DESTRUCTORBODY_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "destructorbody_context"; //$NON-NLS-1$ + public static final String METHODBODY_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "methodbody_context"; //$NON-NLS-1$ public static final String FILECOMMENT_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "filecomment_context"; //$NON-NLS-1$ public static final String TYPECOMMENT_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "typecomment_context"; //$NON-NLS-1$ public static final String FIELDCOMMENT_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "fieldcomment_context"; //$NON-NLS-1$ @@ -41,16 +44,20 @@ public class CodeTemplateContextType extends FileTemplateContextType { public static final String CONSTRUCTORCOMMENT_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "constructorcomment_context"; //$NON-NLS-1$ public static final String DESTRUCTORCOMMENT_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "destructorcomment_context"; //$NON-NLS-1$ - /* templates */ + /* Templates */ private static final String CODETEMPLATES_PREFIX= "org.eclipse.cdt.ui.text.codetemplates."; //$NON-NLS-1$ public static final String COMMENT_SUFFIX= "comment"; //$NON-NLS-1$ - - public static final String ASM_SOURCEFILE_ID= CODETEMPLATES_PREFIX + "asmsourcefile"; //$NON-NLS-1$ - public static final String CPP_SOURCEFILE_ID= CODETEMPLATES_PREFIX + "cppsourcefile"; //$NON-NLS-1$ - public static final String CPP_HEADERFILE_ID= CODETEMPLATES_PREFIX + "cppheaderfile"; //$NON-NLS-1$ - public static final String C_SOURCEFILE_ID= CODETEMPLATES_PREFIX + "csourcefile"; //$NON-NLS-1$ - public static final String C_HEADERFILE_ID= CODETEMPLATES_PREFIX + "cheaderfile"; //$NON-NLS-1$ - public static final String METHODSTUB_ID= CODETEMPLATES_PREFIX + "methodbody"; //$NON-NLS-1$ + + public static final String ASM_SOURCEFILE_ID= CODETEMPLATES_PREFIX + "asmsourcefile"; //$NON-NLS-1$ + public static final String CPP_SOURCEFILE_ID= CODETEMPLATES_PREFIX + "cppsourcefile"; //$NON-NLS-1$ + public static final String CPP_HEADERFILE_ID= CODETEMPLATES_PREFIX + "cppheaderfile"; //$NON-NLS-1$ + public static final String CPP_TESTFILE_ID= CODETEMPLATES_PREFIX + "cpptestfile"; //$NON-NLS-1$ + public static final String C_SOURCEFILE_ID= CODETEMPLATES_PREFIX + "csourcefile"; //$NON-NLS-1$ + public static final String C_HEADERFILE_ID= CODETEMPLATES_PREFIX + "cheaderfile"; //$NON-NLS-1$ + public static final String NAMESPACE_BEGIN_ID= CODETEMPLATES_PREFIX + "namespace_begin"; //$NON-NLS-1$ + public static final String NAMESPACE_END_ID= CODETEMPLATES_PREFIX + "namespace_end"; //$NON-NLS-1$ + public static final String CLASS_BODY_ID= CODETEMPLATES_PREFIX + "class_body"; //$NON-NLS-1$ + public static final String METHODSTUB_ID= CODETEMPLATES_PREFIX + "methodbody"; //$NON-NLS-1$ public static final String CONSTRUCTORSTUB_ID= CODETEMPLATES_PREFIX + "constructorbody"; //$NON-NLS-1$ public static final String DESTRUCTORSTUB_ID= CODETEMPLATES_PREFIX + "destructorbody"; //$NON-NLS-1$ public static final String FILECOMMENT_ID= CODETEMPLATES_PREFIX + "file" + COMMENT_SUFFIX; //$NON-NLS-1$ @@ -60,7 +67,7 @@ public class CodeTemplateContextType extends FileTemplateContextType { public static final String CONSTRUCTORCOMMENT_ID= CODETEMPLATES_PREFIX + "constructor" + COMMENT_SUFFIX; //$NON-NLS-1$ public static final String DESTRUCTORCOMMENT_ID= CODETEMPLATES_PREFIX + "destructor" + COMMENT_SUFFIX; //$NON-NLS-1$ - /* resolver types */ + /* Resolver types */ public static final String ENCLOSING_METHOD= "enclosing_method"; //$NON-NLS-1$ public static final String ENCLOSING_TYPE= "enclosing_type"; //$NON-NLS-1$ public static final String BODY_STATEMENT= "body_statement"; //$NON-NLS-1$ @@ -70,11 +77,16 @@ public class CodeTemplateContextType extends FileTemplateContextType { public static final String RETURN_TYPE= "return_type"; //$NON-NLS-1$ public static final String TYPENAME= "type_name"; //$NON-NLS-1$ + public static final String NAMESPACE_NAME= "namespace_name"; //$NON-NLS-1$ + public static final String BASE_CLASSES= "base_classes"; //$NON-NLS-1$ public static final String INCLUDE_GUARD_SYMBOL= "include_guard_symbol"; //$NON-NLS-1$ public static final String DECLARATIONS= "declarations"; //$NON-NLS-1$ public static final String TYPE_COMMENT= "typecomment"; //$NON-NLS-1$ public static final String FILE_COMMENT= "filecomment"; //$NON-NLS-1$ + public static final String INCLUDES= "includes"; //$NON-NLS-1$ + public static final String NAMESPACE_BEGIN= "namespace_begin"; //$NON-NLS-1$ + public static final String NAMESPACE_END= "namespace_end"; //$NON-NLS-1$ /** * Resolver that resolves to the variable defined in the context. @@ -123,34 +135,53 @@ public class CodeTemplateContextType extends FileTemplateContextType { if (CPPSOURCEFILE_CONTEXTTYPE.equals(contextTypeId)) { addResolver(new CodeTemplateVariableResolver(DECLARATIONS, TemplateMessages.CodeTemplateContextType_variable_description_typedeclaration)); - addResolver(new CodeTemplateVariableResolver(TYPE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_typecomment)); addResolver(new CodeTemplateVariableResolver(FILE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_filecomment)); + addResolver(new CodeTemplateVariableResolver(INCLUDES, TemplateMessages.CodeTemplateContextType_variable_description_includes)); + addResolver(new CodeTemplateVariableResolver(NAMESPACE_BEGIN, TemplateMessages.CodeTemplateContextType_variable_description_namespace_begin)); + addResolver(new CodeTemplateVariableResolver(NAMESPACE_END, TemplateMessages.CodeTemplateContextType_variable_description_namespace_end)); + addResolver(new CodeTemplateVariableResolver(NAMESPACE_NAME, TemplateMessages.CodeTemplateContextType_variable_description_namespace_name)); + addResolver(new CodeTemplateVariableResolver(TYPE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_typecomment)); + addResolver(new CodeTemplateVariableResolver(TYPENAME, TemplateMessages.CodeTemplateContextType_variable_description_class_name)); addTranslationUnitVariables(); } else if (CPPHEADERFILE_CONTEXTTYPE.equals(contextTypeId)) { - addResolver(new CodeTemplateVariableResolver(INCLUDE_GUARD_SYMBOL, TemplateMessages.CodeTemplateContextType_variable_description_include_guard_symbol)); addResolver(new CodeTemplateVariableResolver(DECLARATIONS, TemplateMessages.CodeTemplateContextType_variable_description_typedeclaration)); - addResolver(new CodeTemplateVariableResolver(TYPE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_typecomment)); addResolver(new CodeTemplateVariableResolver(FILE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_filecomment)); + addResolver(new CodeTemplateVariableResolver(INCLUDE_GUARD_SYMBOL, TemplateMessages.CodeTemplateContextType_variable_description_include_guard_symbol)); + addResolver(new CodeTemplateVariableResolver(INCLUDES, TemplateMessages.CodeTemplateContextType_variable_description_includes)); + addResolver(new CodeTemplateVariableResolver(NAMESPACE_BEGIN, TemplateMessages.CodeTemplateContextType_variable_description_namespace_begin)); + addResolver(new CodeTemplateVariableResolver(NAMESPACE_END, TemplateMessages.CodeTemplateContextType_variable_description_namespace_end)); + addResolver(new CodeTemplateVariableResolver(NAMESPACE_NAME, TemplateMessages.CodeTemplateContextType_variable_description_namespace_name)); + addResolver(new CodeTemplateVariableResolver(TYPE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_typecomment)); + addResolver(new CodeTemplateVariableResolver(TYPENAME, TemplateMessages.CodeTemplateContextType_variable_description_class_name)); addTranslationUnitVariables(); } else if (CSOURCEFILE_CONTEXTTYPE.equals(contextTypeId)) { addResolver(new CodeTemplateVariableResolver(DECLARATIONS, TemplateMessages.CodeTemplateContextType_variable_description_typedeclaration)); addResolver(new CodeTemplateVariableResolver(FILE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_filecomment)); + addResolver(new CodeTemplateVariableResolver(INCLUDES, TemplateMessages.CodeTemplateContextType_variable_description_includes)); addTranslationUnitVariables(); } else if (CHEADERFILE_CONTEXTTYPE.equals(contextTypeId)) { - addResolver(new CodeTemplateVariableResolver(INCLUDE_GUARD_SYMBOL, TemplateMessages.CodeTemplateContextType_variable_description_include_guard_symbol)); addResolver(new CodeTemplateVariableResolver(DECLARATIONS, TemplateMessages.CodeTemplateContextType_variable_description_typedeclaration)); addResolver(new CodeTemplateVariableResolver(FILE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_filecomment)); + addResolver(new CodeTemplateVariableResolver(INCLUDE_GUARD_SYMBOL, TemplateMessages.CodeTemplateContextType_variable_description_include_guard_symbol)); + addResolver(new CodeTemplateVariableResolver(INCLUDES, TemplateMessages.CodeTemplateContextType_variable_description_includes)); addTranslationUnitVariables(); } else if (METHODBODY_CONTEXTTYPE.equals(contextTypeId)) { - addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_enclosingtype)); + addResolver(new CodeTemplateVariableResolver(BODY_STATEMENT, TemplateMessages.CodeTemplateContextType_variable_description_bodystatement)); addResolver(new CodeTemplateVariableResolver(ENCLOSING_METHOD, TemplateMessages.CodeTemplateContextType_variable_description_enclosingmethod)); - addResolver(new CodeTemplateVariableResolver(BODY_STATEMENT, TemplateMessages.CodeTemplateContextType_variable_description_bodystatement)); + addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_enclosingtype)); } else if (CONSTRUCTORBODY_CONTEXTTYPE.equals(contextTypeId)) { - addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_enclosingtype)); addResolver(new CodeTemplateVariableResolver(BODY_STATEMENT, TemplateMessages.CodeTemplateContextType_variable_description_bodystatement)); + addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_enclosingtype)); } else if (DESTRUCTORBODY_CONTEXTTYPE.equals(contextTypeId)) { - addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_enclosingtype)); addResolver(new CodeTemplateVariableResolver(BODY_STATEMENT, TemplateMessages.CodeTemplateContextType_variable_description_bodystatement)); + addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_enclosingtype)); + } else if (CLASS_BODY_CONTEXTTYPE.equals(contextTypeId)) { + addResolver(new CodeTemplateVariableResolver(DECLARATIONS, TemplateMessages.CodeTemplateContextType_variable_description_class_members)); + addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_class_name)); + } else if (NAMESPACE_CONTEXTTYPE.equals(contextTypeId)) { + addResolver(new CodeTemplateVariableResolver(NAMESPACE_BEGIN, TemplateMessages.CodeTemplateContextType_variable_description_namespace_begin)); + addResolver(new CodeTemplateVariableResolver(NAMESPACE_END, TemplateMessages.CodeTemplateContextType_variable_description_namespace_end)); + addResolver(new CodeTemplateVariableResolver(NAMESPACE_NAME, TemplateMessages.CodeTemplateContextType_variable_description_namespace_name)); } else if (TYPECOMMENT_CONTEXTTYPE.equals(contextTypeId)) { addResolver(new CodeTemplateVariableResolver(TYPENAME, TemplateMessages.CodeTemplateContextType_variable_description_typename)); addTranslationUnitVariables(); @@ -159,13 +190,13 @@ public class CodeTemplateContextType extends FileTemplateContextType { addTranslationUnitVariables(); fIsComment= true; } else if (FIELDCOMMENT_CONTEXTTYPE.equals(contextTypeId)) { - addResolver(new CodeTemplateVariableResolver(FIELD_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_fieldtype)); addResolver(new CodeTemplateVariableResolver(FIELD, TemplateMessages.CodeTemplateContextType_variable_description_fieldname)); + addResolver(new CodeTemplateVariableResolver(FIELD_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_fieldtype)); addTranslationUnitVariables(); fIsComment= true; } else if (METHODCOMMENT_CONTEXTTYPE.equals(contextTypeId)) { - addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_enclosingtype)); addResolver(new CodeTemplateVariableResolver(ENCLOSING_METHOD, TemplateMessages.CodeTemplateContextType_variable_description_enclosingmethod)); + addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_enclosingtype)); addResolver(new CodeTemplateVariableResolver(RETURN_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_returntype)); addTranslationUnitVariables(); fIsComment= true; @@ -203,9 +234,11 @@ public class CodeTemplateContextType extends FileTemplateContextType { asmContextType.addResolver(new CodeTemplateVariableResolver(FILE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_filecomment)); registry.addContextType(asmContextType); - registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.METHODBODY_CONTEXTTYPE)); + registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.NAMESPACE_CONTEXTTYPE)); + registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.CLASS_BODY_CONTEXTTYPE)); registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.CONSTRUCTORBODY_CONTEXTTYPE)); registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.DESTRUCTORBODY_CONTEXTTYPE)); + registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.METHODBODY_CONTEXTTYPE)); registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.FILECOMMENT_CONTEXTTYPE)); registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.TYPECOMMENT_CONTEXTTYPE)); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.java index fa3b10f93a5..5e159189d82 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.java @@ -9,19 +9,13 @@ * IBM Corporation - initial API and implementation * QnX Software System * Anton Leherbauer (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.corext.template.c; import org.eclipse.osgi.util.NLS; public final class TemplateMessages extends NLS { - - private static final String BUNDLE_NAME = "org.eclipse.cdt.internal.corext.template.c.TemplateMessages";//$NON-NLS-1$ - - private TemplateMessages() { - // Do not instantiate - } - public static String CContextType_variable_description_file; public static String CContextType_variable_description_file_base; public static String CContextType_variable_description_enclosing_method; @@ -32,11 +26,18 @@ public final class TemplateMessages extends NLS { public static String CodeTemplateContextType_variable_description_todo; public static String CodeTemplateContextType_variable_description_typedeclaration; + public static String CodeTemplateContextType_variable_description_class_members; public static String CodeTemplateContextType_variable_description_fieldname; public static String CodeTemplateContextType_variable_description_fieldtype; public static String CodeTemplateContextType_variable_description_typecomment; public static String CodeTemplateContextType_variable_description_enclosingtype; + public static String CodeTemplateContextType_variable_description_includes; + public static String CodeTemplateContextType_variable_description_namespace_begin; + public static String CodeTemplateContextType_variable_description_namespace_end; + public static String CodeTemplateContextType_variable_description_namespace_name; public static String CodeTemplateContextType_variable_description_typename; + public static String CodeTemplateContextType_variable_description_class_name; + public static String CodeTemplateContextType_variable_description_base_classes; public static String CodeTemplateContextType_variable_description_include_guard_symbol; public static String CodeTemplateContextType_variable_description_enclosingmethod; public static String CodeTemplateContextType_variable_description_bodystatement; @@ -60,6 +61,10 @@ public final class TemplateMessages extends NLS { public static String FileTemplateContextType_variable_description_projectname; static { - NLS.initializeMessages(BUNDLE_NAME, TemplateMessages.class); + NLS.initializeMessages(TemplateMessages.class.getName(), TemplateMessages.class); + } + + // Do not instantiate. + private TemplateMessages() { } } \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.properties index b4401be3b06..95a3b7dac63 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.properties @@ -9,6 +9,7 @@ # IBM Corporation - initial API and implementation # QnX Software System # Anton Leherbauer (Wind River Systems) +# Sergey Prigogin (Google) ######################################### CContextType_variable_description_file=Name of source file @@ -21,11 +22,18 @@ CContextType_variable_description_todo=Todo task tag CodeTemplateContextType_variable_description_todo=Todo task tag CodeTemplateContextType_variable_description_typedeclaration=Generated type declaration +CodeTemplateContextType_variable_description_class_members=Generated declarations of class members CodeTemplateContextType_variable_description_fieldname=The name of field CodeTemplateContextType_variable_description_fieldtype=The type of the field CodeTemplateContextType_variable_description_typecomment=Content of code template 'Comments > Types' CodeTemplateContextType_variable_description_enclosingtype=The enclosing type +CodeTemplateContextType_variable_description_includes=Generated include statements +CodeTemplateContextType_variable_description_namespace_begin=Beginning of namespace declaration +CodeTemplateContextType_variable_description_namespace_end=End of namespace declaration +CodeTemplateContextType_variable_description_namespace_name=Name of the current namespace +CodeTemplateContextType_variable_description_class_name=Name of the current class CodeTemplateContextType_variable_description_typename=Name of the current type +CodeTemplateContextType_variable_description_base_classes=Base clauses CodeTemplateContextType_variable_description_include_guard_symbol=Include guard symbol CodeTemplateContextType_variable_description_enclosingmethod=The enclosing method CodeTemplateContextType_variable_description_bodystatement=Return statement or super call diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/Strings.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/Strings.java index 10e822ba8c7..8242e9cdd5b 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/Strings.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/Strings.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -24,12 +24,11 @@ import org.eclipse.osgi.util.TextProcessor; import org.eclipse.cdt.core.formatter.IndentManipulation; import org.eclipse.cdt.core.model.ICProject; - /** * Helper class to provide String manipulation functions not available in standard JDK. */ public class Strings { - + private Strings() {} /** @@ -46,7 +45,7 @@ public class Strings { private static final String C_ELEMENT_DELIMITERS= TextProcessor.getDefaultDelimiters() + "<>(),?{} "; //$NON-NLS-1$ - public static boolean startsWithIgnoreCase(String text, String prefix) { + public static boolean startsWithIgnoreCase(CharSequence text, CharSequence prefix) { int textLength= text.length(); int prefixLength= prefix.length(); if (textLength < prefixLength) @@ -58,6 +57,17 @@ public class Strings { return true; } + public static boolean endsWith(CharSequence containing, CharSequence contained) { + int start = containing.length() - contained.length(); + if (start < 0) + return false; + for (int i = start, j = 0; i < containing.length(); i++, j++) { + if (containing.charAt(i) != contained.charAt(j)) + return false; + } + return true; + } + public static String removeNewLine(String message) { StringBuffer result= new StringBuffer(); int current= 0; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeTemplateBlock.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeTemplateBlock.java index 83eb79e4e5d..e081001666b 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeTemplateBlock.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeTemplateBlock.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -9,6 +9,7 @@ * IBM Corporation - initial API and implementation * Anton Leherbauer (Wind River Systems) * Andrew Ferguson (Symbian) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.ui.preferences; @@ -112,7 +113,7 @@ public class CodeTemplateBlock extends OptionsConfigurationBlock { } else if (element == FILE_NODE) { return getFileTemplateContextTypes(); } else if (element instanceof TemplateContextType) { - return getTemplatesOfContextType(((TemplateContextType)element).getId()); + return getTemplatesOfContextType(((TemplateContextType) element).getId()); } return NO_CHILDREN; } @@ -147,7 +148,7 @@ public class CodeTemplateBlock extends OptionsConfigurationBlock { } /* - * @see org.eclipse.jface.viewers.ViewerSorter#category(java.lang.Object) + * @see org.eclipse.jface.viewers.ViewerComparator#category(java.lang.Object) */ @Override public int category(Object element) { @@ -181,12 +182,18 @@ public class CodeTemplateBlock extends OptionsConfigurationBlock { if (CodeTemplateContextType.ASMSOURCEFILE_CONTEXTTYPE.equals(id)) { return 105; - } else if (CodeTemplateContextType.METHODSTUB_ID.equals(id)) { + } else if (CodeTemplateContextType.NAMESPACE_BEGIN_ID.equals(id)) { return 106; - } else if (CodeTemplateContextType.CONSTRUCTORSTUB_ID.equals(id)) { + } else if (CodeTemplateContextType.NAMESPACE_END_ID.equals(id)) { return 107; - } else if (CodeTemplateContextType.DESTRUCTORSTUB_ID.equals(id)) { + } else if (CodeTemplateContextType.CLASS_BODY_ID.equals(id)) { return 108; + } else if (CodeTemplateContextType.METHODSTUB_ID.equals(id)) { + return 109; + } else if (CodeTemplateContextType.CONSTRUCTORSTUB_ID.equals(id)) { + return 110; + } else if (CodeTemplateContextType.DESTRUCTORSTUB_ID.equals(id)) { + return 111; } else if (CodeTemplateContextType.FILECOMMENT_ID.equals(id)) { return 1; } else if (CodeTemplateContextType.TYPECOMMENT_ID.equals(id)) { @@ -251,18 +258,24 @@ public class CodeTemplateBlock extends OptionsConfigurationBlock { return (String) element; } if (element instanceof TemplateContextType) { - return ((TemplateContextType)element).getName(); + return ((TemplateContextType) element).getName(); } TemplatePersistenceData data= (TemplatePersistenceData) element; String id= data.getId(); if (FileTemplateContextType.isFileTemplateContextType(data.getTemplate().getContextTypeId())) { return data.getTemplate().getName(); - } else if (CodeTemplateContextType.METHODSTUB_ID.equals(id)) { - return PreferencesMessages.CodeTemplateBlock_methodstub_label; + } else if (CodeTemplateContextType.NAMESPACE_BEGIN_ID.equals(id)) { + return PreferencesMessages.CodeTemplateBlock_namespace_begin_label; + } else if (CodeTemplateContextType.NAMESPACE_END_ID.equals(id)) { + return PreferencesMessages.CodeTemplateBlock_namespace_end_label; + } else if (CodeTemplateContextType.CLASS_BODY_ID.equals(id)) { + return PreferencesMessages.CodeTemplateBlock_class_body_label; } else if (CodeTemplateContextType.CONSTRUCTORSTUB_ID.equals(id)) { return PreferencesMessages.CodeTemplateBlock_constructorstub_label; } else if (CodeTemplateContextType.DESTRUCTORSTUB_ID.equals(id)) { return PreferencesMessages.CodeTemplateBlock_destructorstub_label; + } else if (CodeTemplateContextType.METHODSTUB_ID.equals(id)) { + return PreferencesMessages.CodeTemplateBlock_methodstub_label; } else if (CodeTemplateContextType.FILECOMMENT_ID.equals(id)) { return PreferencesMessages.CodeTemplateBlock_filecomment_label; } else if (CodeTemplateContextType.TYPECOMMENT_ID.equals(id)) { @@ -310,7 +323,8 @@ public class CodeTemplateBlock extends OptionsConfigurationBlock { private TemplateVariableProcessor fTemplateProcessor; private ContextTypeRegistry fFileTemplateContextTypes; - public CodeTemplateBlock(IStatusChangeListener context, IProject project, IWorkbenchPreferenceContainer container) { + public CodeTemplateBlock(IStatusChangeListener context, IProject project, + IWorkbenchPreferenceContainer container) { super(context, project, getAllKeys(), container); fTemplateStore= new ProjectTemplateStore(project); @@ -387,7 +401,7 @@ public class CodeTemplateBlock extends OptionsConfigurationBlock { fCodeTemplateTree.doFillIntoGrid(composite, 3); LayoutUtil.setHorizontalSpan(fCodeTemplateTree.getLabelControl(null), 2); - LayoutUtil.setHorizontalGrabbing(fCodeTemplateTree.getTreeControl(null)); + LayoutUtil.setHorizontalGrabbing(fCodeTemplateTree.getTreeControl(null), true); fPatternViewer= createViewer(composite, 2); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/NameStyleBlock.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/NameStyleBlock.java index 8ee4b80cc10..b42b007b03b 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/NameStyleBlock.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/NameStyleBlock.java @@ -186,14 +186,6 @@ public class NameStyleBlock extends OptionsConfigurationBlock { .setSeedNameGenerator(fieldCategory) .setNameValidator(IDENTIFIER_VALIDATOR); Category fileCategory = new Category(PreferencesMessages.NameStyleBlock_files_node); - new Category(PreferencesMessages.NameStyleBlock_cpp_source_node, - PreferencesMessages.NameStyleBlock_cpp_source_node_description, EXAMPLE_CLASS_NAME, - fileCategory) - .setCapitalizationKey(KEY_CPP_SOURCE_CAPITALIZATION) - .setWordDelimiterKey(KEY_CPP_SOURCE_WORD_DELIMITER) - .setPrefixKey(KEY_CPP_SOURCE_PREFIX) - .setSuffixKey(KEY_CPP_SOURCE_SUFFIX) - .setNameValidator(FILENAME_VALIDATOR); new Category(PreferencesMessages.NameStyleBlock_cpp_header_node, PreferencesMessages.NameStyleBlock_cpp_header_node_description, EXAMPLE_CLASS_NAME, fileCategory) @@ -202,10 +194,17 @@ public class NameStyleBlock extends OptionsConfigurationBlock { .setPrefixKey(KEY_CPP_HEADER_PREFIX) .setSuffixKey(KEY_CPP_HEADER_SUFFIX) .setNameValidator(FILENAME_VALIDATOR); - // TODO(sprigogin): Unhide the test name style category + new Category(PreferencesMessages.NameStyleBlock_cpp_source_node, + PreferencesMessages.NameStyleBlock_cpp_source_node_description, EXAMPLE_CLASS_NAME, + fileCategory) + .setCapitalizationKey(KEY_CPP_SOURCE_CAPITALIZATION) + .setWordDelimiterKey(KEY_CPP_SOURCE_WORD_DELIMITER) + .setPrefixKey(KEY_CPP_SOURCE_PREFIX) + .setSuffixKey(KEY_CPP_SOURCE_SUFFIX) + .setNameValidator(FILENAME_VALIDATOR); new Category(PreferencesMessages.NameStyleBlock_cpp_test_node, PreferencesMessages.NameStyleBlock_cpp_test_node_description, EXAMPLE_CLASS_NAME, - null) // Hidden for now. + fileCategory) .setCapitalizationKey(KEY_CPP_TEST_CAPITALIZATION) .setWordDelimiterKey(KEY_CPP_TEST_WORD_DELIMITER) .setPrefixKey(KEY_CPP_TEST_PREFIX) diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java index 13cd389f659..1876973a9f9 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java @@ -336,9 +336,13 @@ public final class PreferencesMessages extends NLS { public static String CodeTemplateBlock_templates_comment_node; public static String CodeTemplateBlock_templates_code_node; public static String CodeTemplateBlock_templates_file_node; - public static String CodeTemplateBlock_methodstub_label; + + public static String CodeTemplateBlock_namespace_begin_label; + public static String CodeTemplateBlock_namespace_end_label; + public static String CodeTemplateBlock_class_body_label; public static String CodeTemplateBlock_constructorstub_label; public static String CodeTemplateBlock_destructorstub_label; + public static String CodeTemplateBlock_methodstub_label; public static String CodeTemplateBlock_typecomment_label; public static String CodeTemplateBlock_fieldcomment_label; public static String CodeTemplateBlock_filecomment_label; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties index 092b51a35ae..0c71a2db623 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties @@ -389,9 +389,12 @@ CodeTemplateBlock_templates_comment_node=Comments CodeTemplateBlock_templates_code_node=Code CodeTemplateBlock_templates_file_node=Files -CodeTemplateBlock_methodstub_label=Method body +CodeTemplateBlock_namespace_begin_label=Beginning of namespace declaration +CodeTemplateBlock_namespace_end_label=End of namespace declaration +CodeTemplateBlock_class_body_label=Class body CodeTemplateBlock_constructorstub_label=Constructor body CodeTemplateBlock_destructorstub_label=Destructor body +CodeTemplateBlock_methodstub_label=Method body CodeTemplateBlock_typecomment_label=Types CodeTemplateBlock_fieldcomment_label=Fields CodeTemplateBlock_filecomment_label=Files @@ -406,7 +409,7 @@ CodeTemplateBlock_templates_import_button=I&mport... CodeTemplateBlock_templates_export_button=E&xport... CodeTemplateBlock_templates_exportall_button=Ex&port All... -CodeTemplateBlock_createcomment_label=Automatically add comments &for new methods and classes +CodeTemplateBlock_createcomment_label=&Automatically add comments for new methods and classes CodeTemplateBlock_templates_label=&Configure generated code and comments: CodeTemplateBlock_preview=Pa&ttern: diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCodeGenerator.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCodeGenerator.java index f64de1012c7..0631ec5985b 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCodeGenerator.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCodeGenerator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2009 QNX Software Systems and others. + * Copyright (c) 2004, 2011 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,6 +10,7 @@ * IBM Corporation * Warren Paul (Nokia) - 173555 * Anton Leherbauer (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.ui.wizards.classwizard; @@ -30,7 +31,10 @@ import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.text.edits.DeleteEdit; import org.eclipse.text.edits.MalformedTreeException; +import org.eclipse.text.edits.MultiTextEdit; import org.eclipse.text.edits.TextEdit; import org.eclipse.cdt.core.CCorePlugin; @@ -57,20 +61,24 @@ import org.eclipse.cdt.utils.PathUtil; import org.eclipse.cdt.internal.corext.codemanipulation.StubUtility; import org.eclipse.cdt.internal.corext.util.CModelUtil; import org.eclipse.cdt.internal.corext.util.CodeFormatterUtil; +import org.eclipse.cdt.internal.corext.util.Strings; +import org.eclipse.cdt.internal.formatter.scanner.Scanner; +import org.eclipse.cdt.internal.formatter.scanner.Token; import org.eclipse.cdt.internal.ui.wizards.filewizard.NewSourceFileGenerator; public class NewClassCodeGenerator { - - private IPath fHeaderPath = null; - private IPath fSourcePath = null; - private String fClassName = null; - private IQualifiedTypeName fNamespace = null; - private IBaseClassInfo[] fBaseClasses = null; - private IMethodStub[] fMethodStubs = null; - private ITranslationUnit fCreatedHeaderTU = null; - private ITranslationUnit fCreatedSourceTU = null; - private ICElement fCreatedClass = null; + private final IPath fHeaderPath; + private final IPath fSourcePath; + private final IPath fTestPath; + private String fClassName; + private IQualifiedTypeName fNamespace; + private final IBaseClassInfo[] fBaseClasses; + private final IMethodStub[] fMethodStubs; + private ITranslationUnit fCreatedHeaderTU; + private ITranslationUnit fCreatedSourceTU; + private ITranslationUnit fCreatedTestTU; + private ICElement fCreatedClass; private String fFullyQualifiedClassName; private boolean fForceSourceFileCreation; @@ -97,9 +105,20 @@ public class NewClassCodeGenerator { } } - public NewClassCodeGenerator(IPath headerPath, IPath sourcePath, String className, String namespace, IBaseClassInfo[] baseClasses, IMethodStub[] methodStubs) { + /** + * @param headerPath the header file path + * @param sourcePath the source file path + * @param testPath the test file path, can be {@code null} + * @param className the class name + * @param namespace the namespace name + * @param baseClasses the base classes + * @param methodStubs the method stubs + */ + public NewClassCodeGenerator(IPath headerPath, IPath sourcePath, IPath testPath, + String className, String namespace, IBaseClassInfo[] baseClasses, IMethodStub[] methodStubs) { fHeaderPath = headerPath; fSourcePath = sourcePath; + fTestPath = testPath; if (className != null && className.length() > 0) { fClassName = className; } @@ -125,7 +144,7 @@ public class NewClassCodeGenerator { public IFile getCreatedHeaderFile() { if (fCreatedHeaderTU != null) { - return (IFile)fCreatedHeaderTU.getResource(); + return (IFile) fCreatedHeaderTU.getResource(); } return null; } @@ -136,7 +155,14 @@ public class NewClassCodeGenerator { public IFile getCreatedSourceFile() { if (fCreatedSourceTU != null) { - return (IFile)fCreatedSourceTU.getResource(); + return (IFile) fCreatedSourceTU.getResource(); + } + return null; + } + + public IFile getCreatedTestFile() { + if (fCreatedTestTU != null) { + return (IFile) fCreatedTestTU.getResource(); } return null; } @@ -151,7 +177,8 @@ public class NewClassCodeGenerator { * @throws InterruptedException * Thrown when the operation was cancelled. */ - public ICElement createClass(IProgressMonitor monitor) throws CodeGeneratorException, CoreException, InterruptedException { + public ICElement createClass(IProgressMonitor monitor) + throws CodeGeneratorException, CoreException, InterruptedException { if (monitor == null) monitor = new NullProgressMonitor(); @@ -159,27 +186,31 @@ public class NewClassCodeGenerator { ITranslationUnit headerTU = null; ITranslationUnit sourceTU = null; + ITranslationUnit testTU = null; ICElement createdClass = null; IWorkingCopy headerWorkingCopy = null; IWorkingCopy sourceWorkingCopy = null; + IWorkingCopy testWorkingCopy = null; try { if (fHeaderPath != null) { - - // get method stubs + // Get method stubs List publicMethods = getStubs(ASTAccessVisibility.PUBLIC, false); List protectedMethods = getStubs(ASTAccessVisibility.PROTECTED, false); List privateMethods = getStubs(ASTAccessVisibility.PRIVATE, false); - IFile headerFile = NewSourceFileGenerator.createHeaderFile(fHeaderPath, true, new SubProgressMonitor(monitor, 50)); + IFile headerFile = NewSourceFileGenerator.createHeaderFile(fHeaderPath, true, + new SubProgressMonitor(monitor, 50)); if (headerFile != null) { headerTU = (ITranslationUnit) CoreModel.getDefault().create(headerFile); - // create a working copy with a new owner + // Create a working copy with a new owner headerWorkingCopy = headerTU.getWorkingCopy(); // headerWorkingCopy = headerTU.getSharedWorkingCopy(null, CUIPlugin.getDefault().getBufferFactory()); - String headerContent = constructHeaderFileContent(headerTU, publicMethods, protectedMethods, privateMethods, headerWorkingCopy.getBuffer().getContents(), new SubProgressMonitor(monitor, 100)); + String headerContent = constructHeaderFileContent(headerTU, publicMethods, + protectedMethods, privateMethods, headerWorkingCopy.getBuffer().getContents(), + new SubProgressMonitor(monitor, 100)); headerContent= formatSource(headerContent, headerTU); headerWorkingCopy.getBuffer().setContents(headerContent); @@ -198,24 +229,27 @@ public class NewClassCodeGenerator { } if (fSourcePath != null) { - - // get method stubs + // Get method stubs List publicMethods = getStubs(ASTAccessVisibility.PUBLIC, true); List protectedMethods = getStubs(ASTAccessVisibility.PROTECTED, true); List privateMethods = getStubs(ASTAccessVisibility.PRIVATE, true); - if (!fForceSourceFileCreation && publicMethods.isEmpty() && protectedMethods.isEmpty() && privateMethods.isEmpty()) { + if (!fForceSourceFileCreation && publicMethods.isEmpty() && + protectedMethods.isEmpty() && privateMethods.isEmpty()) { monitor.worked(100); } else { - IFile sourceFile = NewSourceFileGenerator.createSourceFile(fSourcePath, true, new SubProgressMonitor(monitor, 50)); + IFile sourceFile = NewSourceFileGenerator.createSourceFile(fSourcePath, true, + new SubProgressMonitor(monitor, 50)); if (sourceFile != null) { sourceTU = (ITranslationUnit) CoreModel.getDefault().create(sourceFile); monitor.worked(50); - // create a working copy with a new owner + // Create a working copy with a new owner sourceWorkingCopy = sourceTU.getWorkingCopy(); - String sourceContent = constructSourceFileContent(sourceTU, headerTU, publicMethods, protectedMethods, privateMethods, sourceWorkingCopy.getBuffer().getContents(), new SubProgressMonitor(monitor, 100)); + String sourceContent = constructSourceFileContent(sourceTU, headerTU, + publicMethods, protectedMethods, privateMethods, + sourceWorkingCopy.getBuffer().getContents(), new SubProgressMonitor(monitor, 100)); sourceContent= formatSource(sourceContent, sourceTU); sourceWorkingCopy.getBuffer().setContents(sourceContent); @@ -231,6 +265,33 @@ public class NewClassCodeGenerator { fCreatedSourceTU = sourceTU; } } + + if (fTestPath != null) { + IFile testFile = NewSourceFileGenerator.createTestFile(fTestPath, true, + new SubProgressMonitor(monitor, 50)); + if (testFile != null) { + testTU = (ITranslationUnit) CoreModel.getDefault().create(testFile); + monitor.worked(50); + + // Create a working copy with a new owner + testWorkingCopy = testTU.getWorkingCopy(); + + String testContent = constructTestFileContent(testTU, headerTU, + testWorkingCopy.getBuffer().getContents(), new SubProgressMonitor(monitor, 100)); + testContent= formatSource(testContent, testTU); + testWorkingCopy.getBuffer().setContents(testContent); + + if (monitor.isCanceled()) { + throw new InterruptedException(); + } + + testWorkingCopy.reconcile(); + testWorkingCopy.commit(true, monitor); + monitor.worked(50); + } + + fCreatedTestTU = testTU; + } } finally { if (headerWorkingCopy != null) { headerWorkingCopy.destroy(); @@ -238,6 +299,9 @@ public class NewClassCodeGenerator { if (sourceWorkingCopy != null) { sourceWorkingCopy.destroy(); } + if (testWorkingCopy != null) { + testWorkingCopy.destroy(); + } monitor.done(); } @@ -254,7 +318,8 @@ public class NewClassCodeGenerator { */ private String formatSource(String content, ITranslationUnit tu) throws CModelException { String lineDelimiter= StubUtility.getLineDelimiterUsed(tu); - TextEdit edit= CodeFormatterUtil.format(CodeFormatter.K_TRANSLATION_UNIT, content, 0, lineDelimiter, tu.getCProject().getOptions(true)); + TextEdit edit= CodeFormatterUtil.format(CodeFormatter.K_TRANSLATION_UNIT, content, 0, lineDelimiter, + tu.getCProject().getOptions(true)); if (edit != null) { IDocument doc= new Document(content); try { @@ -269,24 +334,43 @@ public class NewClassCodeGenerator { return content; } - public String constructHeaderFileContent(ITranslationUnit headerTU, List publicMethods, List protectedMethods, List privateMethods, String oldContents, IProgressMonitor monitor) throws CoreException { + public String constructHeaderFileContent(ITranslationUnit headerTU, List publicMethods, + List protectedMethods, List privateMethods, String oldContents, + IProgressMonitor monitor) throws CoreException { monitor.beginTask(NewClassWizardMessages.NewClassCodeGeneration_createType_task_header, 100); String lineDelimiter= StubUtility.getLineDelimiterUsed(headerTU); - if (oldContents != null && oldContents.length() == 0) - oldContents = null; - + String namespaceBegin = fNamespace == null ? + null : constructNamespaceBegin(headerTU, lineDelimiter); + String namespaceEnd = fNamespace == null ? + null : constructNamespaceEnd(headerTU, lineDelimiter); + String classDefinition = constructClassDefinition(headerTU, publicMethods, protectedMethods, + privateMethods, lineDelimiter); + + String includes = null; + if (fBaseClasses != null && fBaseClasses.length > 0) { + includes = constructBaseClassIncludes(headerTU, lineDelimiter, + new SubProgressMonitor(monitor, 50)); + } - StringBuffer text = new StringBuffer(); - - int appendFirstCharPos = -1; if (oldContents != null) { + if (oldContents.length() == 0) { + oldContents = null; + } else if (!oldContents.endsWith(lineDelimiter)) { + oldContents += lineDelimiter; + } + } + + String fileContent; + if (oldContents != null) { + int appendFirstCharPos = -1; + StringBuilder text = new StringBuilder(); int insertionPos = getClassDefInsertionPos(oldContents); if (insertionPos == -1) { text.append(oldContents); } else { - // skip over whitespace + // Skip over whitespace int prependLastCharPos = insertionPos - 1; while (prependLastCharPos >= 0 && Character.isWhitespace(oldContents.charAt(prependLastCharPos))) { --prependLastCharPos; @@ -298,64 +382,137 @@ public class NewClassCodeGenerator { } text.append(lineDelimiter); - // insert a blank line before class definition + // Insert a blank line before class definition text.append(lineDelimiter); - } - - if (fBaseClasses != null && fBaseClasses.length > 0) { - addBaseClassIncludes(headerTU, text, lineDelimiter, new SubProgressMonitor(monitor, 50)); - text.append(lineDelimiter); - } - - if (fNamespace != null) { - beginNamespace(text, lineDelimiter); - } - - text.append("class "); //$NON-NLS-1$ - text.append(fClassName); - addBaseClassInheritance(text); - text.append(lineDelimiter); - text.append('{'); - text.append(lineDelimiter); - - //TODO sort methods (eg constructor always first?) - if (!publicMethods.isEmpty() - || !protectedMethods.isEmpty() - || !privateMethods.isEmpty()) { - addMethodDeclarations(headerTU, publicMethods, protectedMethods, privateMethods, text, lineDelimiter); - } - - text.append("};"); //$NON-NLS-1$ - text.append(lineDelimiter); - - if (fNamespace != null) { - endNamespace(text, lineDelimiter); - } - - String fileContent; - if (oldContents != null && appendFirstCharPos != -1) { - // insert a blank line after class definition - text.append(lineDelimiter); - - // skip over any extra whitespace - int len = oldContents.length(); - while (appendFirstCharPos < len && Character.isWhitespace(oldContents.charAt(appendFirstCharPos))) { - ++appendFirstCharPos; + if (namespaceBegin != null) { + text.append(namespaceBegin); + text.append(lineDelimiter); + text.append(lineDelimiter); } - if (appendFirstCharPos < len) { - text.append(oldContents.substring(appendFirstCharPos)); + text.append(classDefinition); + if (namespaceEnd != null) { + if (!classDefinition.endsWith(lineDelimiter)) + text.append(lineDelimiter); + text.append(lineDelimiter); + text.append(namespaceEnd); } + if (appendFirstCharPos != -1) { + // Insert a blank line after class definition + text.append(lineDelimiter); + + // Skip over any extra whitespace + int len = oldContents.length(); + while (appendFirstCharPos < len && + Character.isWhitespace(oldContents.charAt(appendFirstCharPos))) { + ++appendFirstCharPos; + } + if (appendFirstCharPos < len) { + text.append(oldContents.substring(appendFirstCharPos)); + } + } + if (Strings.endsWith(text, lineDelimiter)) + text.append(lineDelimiter); fileContent= text.toString(); } else { - String classComment= getClassComment(headerTU, lineDelimiter); - fileContent= CodeGeneration.getHeaderFileContent(headerTU, classComment, text.toString(), lineDelimiter); + String namespaceName = fNamespace == null ? + null : fNamespace.getFullyQualifiedName(); + String classComment = getClassComment(headerTU, lineDelimiter); + fileContent= CodeGeneration.getHeaderFileContent(headerTU, includes, namespaceBegin, + namespaceEnd, namespaceName, classComment, classDefinition, fClassName, + lineDelimiter); } monitor.done(); return fileContent; } - private int getClassDefInsertionPos(String contents) { + public String constructNamespaceBegin(ITranslationUnit tu, String lineDelimiter) throws CoreException { + StringBuilder text = new StringBuilder(); + for (int i = 0; i < fNamespace.segmentCount(); i++) { + String namespaceName = fNamespace.segment(i); + if (i > 0) { + text.append(lineDelimiter); + } + text.append(CodeGeneration.getNamespaceBeginContent(tu, namespaceName, lineDelimiter)); + } + return text.toString(); + } + + public String constructNamespaceEnd(ITranslationUnit tu, String lineDelimiter) throws CoreException { + StringBuilder text = new StringBuilder(); + for (int i = fNamespace.segmentCount(); --i >= 0;) { + String namespaceName = fNamespace.segment(i); + text.append(CodeGeneration.getNamespaceEndContent(tu, namespaceName, lineDelimiter)); + if (i > 0) { + text.append(lineDelimiter); + } + } + return text.toString(); + } + + public String constructClassDefinition(ITranslationUnit tu, List publicMethods, + List protectedMethods, List privateMethods, + String lineDelimiter) throws CoreException { + StringBuilder code = new StringBuilder(); + String comment = getClassComment(tu, lineDelimiter); + if (comment != null) { + code.append(comment); + code.append(lineDelimiter); + } + code.append("class "); //$NON-NLS-1$ + code.append(fClassName); + code.append(constructBaseClassInheritance()); + code.append(" {"); //$NON-NLS-1$ + code.append(lineDelimiter); + String body = constructMethodDeclarations(tu, publicMethods, protectedMethods, + privateMethods, lineDelimiter); + body = CodeGeneration.getClassBodyContent(tu, fClassName, body, lineDelimiter); + code.append(body); + if (!body.endsWith(lineDelimiter)) { + code.append(lineDelimiter); + } + code.append("};"); //$NON-NLS-1$ + return removeRedundantVisibilityLabels(code.toString()); + } + + private String removeRedundantVisibilityLabels(String code) { + Scanner scanner = new Scanner(); + scanner.setSource(code.toCharArray()); + scanner.resetTo(0, code.length()); + IDocument doc = new Document(code); + try { + MultiTextEdit edit = new MultiTextEdit(); + int sectionType = Token.tBADCHAR; + int previousTokenType = Token.tBADCHAR; + int previousTokenOffset = -1; + Token token; + while ((token = scanner.nextToken()) != null) { + if (token.type == Token.tCOLON) { + switch (previousTokenType) { + case Token.t_public: + case Token.t_protected: + case Token.t_private: + if (previousTokenType == sectionType) { + IRegion region1 = doc.getLineInformationOfOffset(previousTokenOffset); + IRegion region2 = doc.getLineInformationOfOffset(token.offset); + edit.addChild(new DeleteEdit(region1.getOffset(), region2.getOffset() + region2.getLength() - region1.getOffset())); + } + sectionType = previousTokenType; + } + } + previousTokenType = token.type; + previousTokenOffset = token.offset; + } + edit.apply(doc, 0); + } catch (MalformedTreeException e) { + CUIPlugin.log(e); + } catch (BadLocationException e) { + CUIPlugin.log(e); + } + return doc.get(); + } + + private int getClassDefInsertionPos(String contents) { if (contents.length() == 0) { return -1; } @@ -412,26 +569,10 @@ public class NewClassCodeGenerator { return StubUtility.doAddComments(tu.getCProject()); } - private void beginNamespace(StringBuffer text, String lineDelimiter) { - for (int i = 0; i < fNamespace.segmentCount(); ++i) { - text.append("namespace "); //$NON-NLS-1$ - text.append(fNamespace.segment(i)); - text.append(lineDelimiter); - text.append('{'); - text.append(lineDelimiter); - text.append(lineDelimiter); - } - } - - private void endNamespace(StringBuffer text, String lineDelimiter) { - for (int i = 0; i < fNamespace.segmentCount(); ++i) { - text.append(lineDelimiter); - text.append("}"); //$NON-NLS-1$ - text.append(lineDelimiter); - } - } - - private void addMethodDeclarations(ITranslationUnit tu, List publicMethods, List protectedMethods, List privateMethods, StringBuffer text, String lineDelimiter) throws CoreException { + private String constructMethodDeclarations(ITranslationUnit tu, List publicMethods, + List protectedMethods, List privateMethods, String lineDelimiter) + throws CoreException { + StringBuilder text = new StringBuilder(); if (!publicMethods.isEmpty()) { text.append("public:"); //$NON-NLS-1$ text.append(lineDelimiter); @@ -444,6 +585,9 @@ public class NewClassCodeGenerator { } if (!protectedMethods.isEmpty()) { + if (text.length() > 0) { + text.append(lineDelimiter); + } text.append("protected:"); //$NON-NLS-1$ text.append(lineDelimiter); for (IMethodStub stub : protectedMethods) { @@ -455,6 +599,9 @@ public class NewClassCodeGenerator { } if (!privateMethods.isEmpty()) { + if (text.length() > 0) { + text.append(lineDelimiter); + } text.append("private:"); //$NON-NLS-1$ text.append(lineDelimiter); for (IMethodStub stub : privateMethods) { @@ -464,6 +611,8 @@ public class NewClassCodeGenerator { text.append(lineDelimiter); } } + + return text.toString(); } private List getStubs(ASTAccessVisibility access, boolean skipInline) { @@ -479,32 +628,35 @@ public class NewClassCodeGenerator { return list; } - private void addBaseClassInheritance(StringBuffer text) { - if (fBaseClasses != null && fBaseClasses.length > 0) { - text.append(" : "); //$NON-NLS-1$ - for (int i = 0; i < fBaseClasses.length; ++i) { - IBaseClassInfo baseClass = fBaseClasses[i]; - String baseClassName = baseClass.getType().getQualifiedTypeName().getFullyQualifiedName(); - if (i > 0) - text.append(", "); //$NON-NLS-1$ - if (baseClass.getAccess() == ASTAccessVisibility.PRIVATE) - text.append("private"); //$NON-NLS-1$ - else if (baseClass.getAccess() == ASTAccessVisibility.PROTECTED) - text.append("private"); //$NON-NLS-1$ - else - text.append("public"); //$NON-NLS-1$ - text.append(' '); - - if (baseClass.isVirtual()) - text.append("virtual "); //$NON-NLS-1$ - - text.append(baseClassName); - } + private String constructBaseClassInheritance() { + if (fBaseClasses == null || fBaseClasses.length == 0) { + return ""; //$NON-NLS-1$ } + StringBuilder text = new StringBuilder(); + text.append(" : "); //$NON-NLS-1$ + for (int i = 0; i < fBaseClasses.length; ++i) { + IBaseClassInfo baseClass = fBaseClasses[i]; + String baseClassName = baseClass.getType().getQualifiedTypeName().getFullyQualifiedName(); + if (i > 0) + text.append(", "); //$NON-NLS-1$ + if (baseClass.getAccess() == ASTAccessVisibility.PRIVATE) + text.append("private"); //$NON-NLS-1$ + else if (baseClass.getAccess() == ASTAccessVisibility.PROTECTED) + text.append("private"); //$NON-NLS-1$ + else + text.append("public"); //$NON-NLS-1$ + text.append(' '); + + if (baseClass.isVirtual()) + text.append("virtual "); //$NON-NLS-1$ + + text.append(baseClassName); + } + return text.toString(); } - private void addBaseClassIncludes(ITranslationUnit headerTU, StringBuffer text, String lineDelimiter, IProgressMonitor monitor) throws CodeGeneratorException { - + private String constructBaseClassIncludes(ITranslationUnit headerTU, String lineDelimiter, + IProgressMonitor monitor) throws CodeGeneratorException { monitor.beginTask(NewClassWizardMessages.NewClassCodeGeneration_createType_task_header_includePaths, 100); ICProject cProject = headerTU.getCProject(); @@ -515,7 +667,7 @@ public class NewClassCodeGenerator { List includePaths = getIncludePaths(headerTU); List baseClassPaths = getBaseClassPaths(verifyBaseClasses()); - // add the missing include paths to the project + // Add the missing include paths to the project if (createIncludePaths()) { List newIncludePaths = getMissingIncludePaths(projectLocation, includePaths, baseClassPaths); if (!newIncludePaths.isEmpty()) { @@ -526,7 +678,7 @@ public class NewClassCodeGenerator { List systemIncludes = new ArrayList(); List localIncludes = new ArrayList(); - // sort the include paths into system and local + // Sort the include paths into system and local for (IPath baseClassLocation : baseClassPaths) { boolean isSystemIncludePath = false; @@ -540,7 +692,8 @@ public class NewClassCodeGenerator { if (includePath == null) includePath = baseClassLocation; - // make the new #include path in the source file only point to a relative file (i.e. now that the path has been included above in the project) + // Make the new #include path in the source file only point to a relative file + // (i.e. now that the path has been included above in the project) includePath = includePath.removeFirstSegments(includePath.segmentCount() - 1).setDevice(null); if (isSystemIncludePath) @@ -549,7 +702,8 @@ public class NewClassCodeGenerator { localIncludes.add(includePath); } - // write the system include paths, e.g. #include + StringBuilder text = new StringBuilder(); + // Write the system include paths, e.g. #include for (IPath includePath : systemIncludes) { if (!(headerTU.getElementName().equals(includePath.toString()))) { String include = getIncludeString(includePath.toString(), true); @@ -558,7 +712,7 @@ public class NewClassCodeGenerator { } } - // write the local include paths, e.g. #include "header.h" + // Write the local include paths, e.g. #include "header.h" for (IPath includePath : localIncludes) { if (!(headerTU.getElementName().equals(includePath.toString()))) { String include = getIncludeString(includePath.toString(), false); @@ -568,6 +722,7 @@ public class NewClassCodeGenerator { } monitor.done(); + return text.toString(); } /** @@ -616,7 +771,8 @@ public class NewClassCodeGenerator { ICProject includeProject = toCProject(PathUtil.getEnclosingProject(folderToAdd)); if (includeProject != null) { - // make sure that the include is made the same way that build properties for projects makes them, so .contains below is a valid check + // Make sure that the include is made the same way that build properties for + // projects makes them, so .contains below is a valid check IIncludeEntry entry = CoreModel.newIncludeEntry(addToResourcePath, null, new Path(includeProject.getProject().getLocationURI().getPath()), true); if (!checkEntryList.contains(entry)) // if the path already exists in the #includes then don't add it @@ -737,30 +893,49 @@ public class NewClassCodeGenerator { return list; } - public String constructSourceFileContent(ITranslationUnit sourceTU, ITranslationUnit headerTU, List publicMethods, List protectedMethods, List privateMethods, String oldContents, IProgressMonitor monitor) throws CoreException { + public String constructSourceFileContent(ITranslationUnit sourceTU, ITranslationUnit headerTU, + List publicMethods, List protectedMethods, + List privateMethods, String oldContents, IProgressMonitor monitor) throws CoreException { monitor.beginTask(NewClassWizardMessages.NewClassCodeGeneration_createType_task_source, 150); String lineDelimiter= StubUtility.getLineDelimiterUsed(sourceTU); - if (oldContents != null && oldContents.length() == 0) - oldContents = null; - - //TODO should use code templates - StringBuffer text = new StringBuffer(); - String includeString = null; if (headerTU != null) { - includeString = getHeaderIncludeString(sourceTU, headerTU, text, new SubProgressMonitor(monitor, 50)); + includeString = getHeaderIncludeString(sourceTU, headerTU, new SubProgressMonitor(monitor, 50)); if (includeString != null) { - // check if file already has the include + // Check if file already has the include. if (oldContents != null && hasInclude(oldContents, includeString)) { - // don't bother to add it + // Don't bother to add it. includeString = null; } } } - - if (includeString != null) { - if (oldContents != null) { + + String methodBodies = null; + if (!publicMethods.isEmpty() || !protectedMethods.isEmpty() || !privateMethods.isEmpty()) { + // TODO sort methods (e.g. constructor always first?) + methodBodies = constructMethodBodies(sourceTU, publicMethods, protectedMethods, + privateMethods, lineDelimiter, new SubProgressMonitor(monitor, 50)); + } + + String namespaceBegin = fNamespace == null ? + null : constructNamespaceBegin(sourceTU, lineDelimiter); + String namespaceEnd = fNamespace == null ? + null : constructNamespaceEnd(sourceTU, lineDelimiter); + + if (oldContents != null) { + if (oldContents.length() == 0) { + oldContents = null; + } else if (!oldContents.endsWith(lineDelimiter)) { + oldContents += lineDelimiter; + } + } + + String fileContent; + if (oldContents != null) { + StringBuilder text = new StringBuilder(); + + if (includeString != null) { int insertionPos = getIncludeInsertionPos(oldContents); if (insertionPos == -1) { text.append(oldContents); @@ -773,48 +948,106 @@ public class NewClassCodeGenerator { text.append(lineDelimiter); text.append(oldContents.substring(insertionPos)); } - } else { - text.append(includeString); - text.append(lineDelimiter); - } - - // add a blank line + } else { + text.append(oldContents); + } + // Add a blank line text.append(lineDelimiter); - } else if (oldContents != null) { - text.append(oldContents); - // add a blank line - text.append(lineDelimiter); - } - - //TODO sort methods (eg constructor always first?) - if (publicMethods.isEmpty() - && protectedMethods.isEmpty() - && privateMethods.isEmpty()) { - // no methods - } else { - if (fNamespace != null) { - beginNamespace(text, lineDelimiter); + if (methodBodies != null) { + if (namespaceBegin != null) { + text.append(namespaceBegin); + text.append(lineDelimiter); + text.append(lineDelimiter); + } + text.append(methodBodies); + if (namespaceEnd != null) { + if (!methodBodies.endsWith(lineDelimiter)) + text.append(lineDelimiter); + text.append(lineDelimiter); + text.append(namespaceEnd); + } } - - addMethodBodies(sourceTU, publicMethods, protectedMethods, privateMethods, text, lineDelimiter, new SubProgressMonitor(monitor, 50)); - - if (fNamespace != null) { - endNamespace(text, lineDelimiter); - } - } - - String fileContent; - if (oldContents != null) { + + if (Strings.endsWith(text, lineDelimiter)) + text.append(lineDelimiter); fileContent = text.toString(); } else { - fileContent= CodeGeneration.getBodyFileContent(sourceTU, null, text.toString(), lineDelimiter); + String namespaceName = fNamespace == null ? + null : fNamespace.getFullyQualifiedName(); + fileContent= CodeGeneration.getBodyFileContent(sourceTU, includeString, namespaceBegin, + namespaceEnd, namespaceName, null, methodBodies, fClassName, lineDelimiter); } monitor.done(); return fileContent; } - private String getHeaderIncludeString(ITranslationUnit sourceTU, ITranslationUnit headerTU, StringBuffer text, IProgressMonitor monitor) { + public String constructTestFileContent(ITranslationUnit testTU, ITranslationUnit headerTU, + String oldContents, IProgressMonitor monitor) throws CoreException { + monitor.beginTask(NewClassWizardMessages.NewClassCodeGeneration_createType_task_source, 150); + + String lineDelimiter= StubUtility.getLineDelimiterUsed(testTU); + + String includeString = null; + if (headerTU != null) { + includeString = getHeaderIncludeString(testTU, headerTU, new SubProgressMonitor(monitor, 50)); + if (includeString != null) { + // Check if file already has the include. + if (oldContents != null && hasInclude(oldContents, includeString)) { + // Don't bother to add it. + includeString = null; + } + } + } + + if (oldContents != null) { + if (oldContents.length() == 0) { + oldContents = null; + } else if (!oldContents.endsWith(lineDelimiter)) { + oldContents += lineDelimiter; + } + } + + String fileContent; + if (oldContents != null) { + StringBuilder text = new StringBuilder(); + + if (includeString != null) { + int insertionPos = getIncludeInsertionPos(oldContents); + if (insertionPos == -1) { + text.append(oldContents); + text.append(lineDelimiter); + text.append(includeString); + text.append(lineDelimiter); + } else { + text.append(oldContents.substring(0, insertionPos)); + text.append(includeString); + text.append(lineDelimiter); + text.append(oldContents.substring(insertionPos)); + } + } else { + text.append(oldContents); + } + + if (Strings.endsWith(text, lineDelimiter)) + text.append(lineDelimiter); + fileContent = text.toString(); + } else { + String namespaceBegin = fNamespace == null ? + null : constructNamespaceBegin(testTU, lineDelimiter); + String namespaceEnd = fNamespace == null ? + null : constructNamespaceEnd(testTU, lineDelimiter); + String namespaceName = fNamespace == null ? + null : fNamespace.getFullyQualifiedName(); + fileContent= CodeGeneration.getTestFileContent(testTU, includeString, namespaceBegin, + namespaceEnd, namespaceName, null, fClassName, lineDelimiter); + } + monitor.done(); + return fileContent; + } + + private String getHeaderIncludeString(ITranslationUnit sourceTU, ITranslationUnit headerTU, + IProgressMonitor monitor) { IProject project = headerTU.getCProject().getProject(); IPath projectLocation = new Path(project.getLocationURI().getPath()); IPath headerLocation = new Path(headerTU.getResource().getLocationURI().getPath()); @@ -825,7 +1058,7 @@ public class NewClassCodeGenerator { if (includePath != null && !projectLocation.isPrefixOf(headerLocation)) { isSystemIncludePath = true; } else if (projectLocation.isPrefixOf(headerLocation) - && projectLocation.isPrefixOf(sourceLocation)) { + && projectLocation.isPrefixOf(sourceLocation)) { includePath = PathUtil.makeRelativePath(headerLocation, sourceLocation.removeLastSegments(1)); } if (includePath == null) @@ -881,7 +1114,7 @@ public class NewClassCodeGenerator { //TODO temporary hack int includePos = contents.lastIndexOf("#include "); //$NON-NLS-1$ if (includePos != -1) { - // find the end of line + // Find the end of line int startPos = includePos + "#include ".length(); //$NON-NLS-1$ int eolPos = findLastLineChar(contents, startPos); if (eolPos != -1) { @@ -894,7 +1127,10 @@ public class NewClassCodeGenerator { return -1; } - private void addMethodBodies(ITranslationUnit tu, List publicMethods, List protectedMethods, List privateMethods, StringBuffer text, String lineDelimiter, IProgressMonitor monitor) throws CoreException { + private String constructMethodBodies(ITranslationUnit tu, List publicMethods, + List protectedMethods, List privateMethods, String lineDelimiter, + IProgressMonitor monitor) throws CoreException { + StringBuilder text = new StringBuilder(); if (!publicMethods.isEmpty()) { for (Iterator i = publicMethods.iterator(); i.hasNext();) { IMethodStub stub = i.next(); @@ -927,10 +1163,11 @@ public class NewClassCodeGenerator { text.append(lineDelimiter); } } + return text.toString(); } private String getIncludeString(String fileName, boolean isSystemInclude) { - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); buf.append("#include "); //$NON-NLS-1$ if (isSystemInclude) buf.append('<'); @@ -977,6 +1214,5 @@ public class NewClassCodeGenerator { } return -1; } - } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardMessages.java index e3fd199b6f3..3c1510f2046 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardMessages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardMessages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2009 QNX Software Systems and others. + * Copyright (c) 2004, 2011 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,19 +7,13 @@ * * Contributors: * QNX Software Systems - initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.ui.wizards.classwizard; import org.eclipse.osgi.util.NLS; public final class NewClassWizardMessages extends NLS { - - private static final String BUNDLE_NAME = "org.eclipse.cdt.internal.ui.wizards.classwizard.NewClassWizardMessages";//$NON-NLS-1$ - - private NewClassWizardMessages() { - // Do not instantiate - } - public static String NewClassCreationWizard_title; public static String NewClassCreationWizardPage_title; public static String NewClassCreationWizardPage_description; @@ -58,7 +52,7 @@ public final class NewClassWizardMessages extends NLS { public static String NewClassCreationWizardPage_methodStubs_label; public static String NewClassCreationWizardPage_error_NotAFile; public static String NewClassCreationWizardPage_error_FolderDoesNotExist; - public static String NewClassCreationWizardPage_useDefaultLocation_label; + public static String NewClassCreationWizardPage_error_LocationUnknown; public static String NewClassCreationWizardPage_headerFile_label; public static String NewClassCreationWizardPage_headerFile_button; public static String NewClassCreationWizardPage_ChooseHeaderFileDialog_title; @@ -75,7 +69,14 @@ public final class NewClassWizardMessages extends NLS { public static String NewClassCreationWizardPage_warning_SourceFileNameDiscouraged; public static String NewClassCreationWizardPage_warning_SourceFileExists; public static String NewClassCreationWizardPage_error_InvalidSourceFileName; - public static String NewClassCreationWizardPage_error_LocationUnknown; + public static String NewClassCreationWizardPage_testFile_label; + public static String NewClassCreationWizardPage_testFile_button; + public static String NewClassCreationWizardPage_ChooseTestFileDialog_title; + public static String NewClassCreationWizardPage_error_EnterTestFileName; + public static String NewClassCreationWizardPage_error_TestFileNotInSourceFolder; + public static String NewClassCreationWizardPage_warning_TestFileNameDiscouraged; + public static String NewClassCreationWizardPage_warning_TestFileExists; + public static String NewClassCreationWizardPage_error_InvalidTestFileName; public static String BaseClassesListDialogField_buttons_add; public static String BaseClassesListDialogField_buttons_remove; public static String BaseClassesListDialogField_buttons_up; @@ -124,6 +125,10 @@ public final class NewClassWizardMessages extends NLS { public static String NewClassCodeGeneration_stub_destructor_name; static { - NLS.initializeMessages(BUNDLE_NAME, NewClassWizardMessages.class); + NLS.initializeMessages(NewClassWizardMessages.class.getName(), NewClassWizardMessages.class); + } + + // Do not instantiate + private NewClassWizardMessages() { } } \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardMessages.properties index c61eadebfb9..db06f35dc59 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardMessages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2004, 2009 QNX Software Systems and others. +# Copyright (c) 2004, 2011 QNX Software Systems and others. # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 # which accompanies this distribution, and is available at @@ -9,6 +9,7 @@ # QNX Software Systems - Initial API and implementation # IBM Corporation # Anton Leherbauer (Wind River Systems) +# Sergey Prigogin (Google) ############################################################################### # ------- NewClassCreationWizard ------- @@ -60,10 +61,10 @@ NewClassCreationWizardPage_methodStubs_label=&Method stubs: NewClassCreationWizardPage_error_NotAFile=''{0}'' is not a file. NewClassCreationWizardPage_error_FolderDoesNotExist=Folder ''{0}'' does not exist. +NewClassCreationWizardPage_error_LocationUnknown=Cannot locate resource. {0} -NewClassCreationWizardPage_useDefaultLocation_label=&Use default NewClassCreationWizardPage_headerFile_label=&Header: -NewClassCreationWizardPage_headerFile_button=Br&owse... +NewClassCreationWizardPage_headerFile_button=Browse... NewClassCreationWizardPage_ChooseHeaderFileDialog_title=Header File Selection NewClassCreationWizardPage_error_EnterHeaderFileName=Header file name is empty. NewClassCreationWizardPage_error_HeaderFileNotInSourceFolder=Header file must be inside source folder. @@ -71,15 +72,23 @@ NewClassCreationWizardPage_warning_HeaderFileNameDiscouraged=Header file name is NewClassCreationWizardPage_warning_HeaderFileExists=Header file already exists. Contents will be appended. NewClassCreationWizardPage_error_InvalidHeaderFileName=Header file name is not valid. {0}. -NewClassCreationWizardPage_sourceFile_button=Br&owse... NewClassCreationWizardPage_sourceFile_label=Sourc&e: +NewClassCreationWizardPage_sourceFile_button=Browse... NewClassCreationWizardPage_ChooseSourceFileDialog_title=Source File Selection NewClassCreationWizardPage_error_EnterSourceFileName=Source file name is empty. NewClassCreationWizardPage_error_SourceFileNotInSourceFolder=Source file must be inside source folder. NewClassCreationWizardPage_warning_SourceFileNameDiscouraged=Source file name is discouraged. {0} NewClassCreationWizardPage_warning_SourceFileExists=Source file already exists. Contents will be appended. NewClassCreationWizardPage_error_InvalidSourceFileName=Source file name is not valid. {0} -NewClassCreationWizardPage_error_LocationUnknown=Cannot locate resource. {0} + +NewClassCreationWizardPage_testFile_label=Unit &Test: +NewClassCreationWizardPage_testFile_button=Browse... +NewClassCreationWizardPage_ChooseTestFileDialog_title=Test File Selection +NewClassCreationWizardPage_error_EnterTestFileName=Test file name is empty. +NewClassCreationWizardPage_error_TestFileNotInSourceFolder=Test file must be inside source folder. +NewClassCreationWizardPage_warning_TestFileNameDiscouraged=Test file name is discouraged. {0} +NewClassCreationWizardPage_warning_TestFileExists=Test file already exists. Contents will be appended. +NewClassCreationWizardPage_error_InvalidTestFileName=Test file name is not valid. {0} # -----------BaseClassesListDialogField ------------- BaseClassesListDialogField_buttons_add=&Add... diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewHeaderFileCreationWizardPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewHeaderFileCreationWizardPage.java index 3f98b6764eb..483089096d0 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewHeaderFileCreationWizardPage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewHeaderFileCreationWizardPage.java @@ -158,7 +158,8 @@ public class NewHeaderFileCreationWizardPage extends AbstractFileCreationWizardP fNewFileTU = (ITranslationUnit) CoreModel.getDefault().create(newFile); if (fNewFileTU != null) { String lineDelimiter= StubUtility.getLineDelimiterUsed(fNewFileTU); - String content= CodeGeneration.getHeaderFileContent(getTemplate(), fNewFileTU, null, null, lineDelimiter); + String content= CodeGeneration.getHeaderFileContent(getTemplate(), + fNewFileTU, lineDelimiter); if (content != null) { fNewFileTU.getBuffer().setContents(content.toCharArray()); fNewFileTU.save(monitor, true); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewSourceFileGenerator.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewSourceFileGenerator.java index 397e6cd86d5..5e9c6a3189e 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewSourceFileGenerator.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewSourceFileGenerator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2007 QNX Software Systems and others. + * Copyright (c) 2004, 2011 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * QNX Software Systems - initial API and implementation * Anton Leherbauer (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.ui.wizards.filewizard; @@ -33,7 +34,6 @@ import org.eclipse.core.runtime.preferences.IPreferencesService; import org.eclipse.ui.dialogs.ContainerGenerator; public class NewSourceFileGenerator { - /** * Creates a header file name from the given class name. This is the file name * to be used when the class is created. eg. "MyClass" -> "MyClass.h" @@ -78,20 +78,51 @@ public class NewSourceFileGenerator { return composer.compose(className); } - public static IFile createHeaderFile(IPath filePath, boolean force, IProgressMonitor monitor) throws CoreException { + /** + * Creates a file name for the unit test from the given class name. This is the file name + * to be used when the test is created. e.g. "MyClass" -> "MyClass_test.cpp" + * + * @param className the class name + * @return the test file name for the given class + */ + public static String generateTestFileNameFromClass(String className) { + IPreferencesService preferences = Platform.getPreferencesService(); + int capitalization = preferences.getInt(CUIPlugin.PLUGIN_ID, + PreferenceConstants.NAME_STYLE_CPP_TEST_CAPITALIZATION, + PreferenceConstants.NAME_STYLE_CAPITALIZATION_ORIGINAL, null); + String wordDelimiter = preferences.getString(CUIPlugin.PLUGIN_ID, + PreferenceConstants.NAME_STYLE_CPP_TEST_WORD_DELIMITER, "", null); //$NON-NLS-1$ + String prefix = preferences.getString(CUIPlugin.PLUGIN_ID, + PreferenceConstants.NAME_STYLE_CPP_TEST_PREFIX, "", null); //$NON-NLS-1$ + String suffix = preferences.getString(CUIPlugin.PLUGIN_ID, + PreferenceConstants.NAME_STYLE_CPP_TEST_SUFFIX, "_test.cpp", null); //$NON-NLS-1$ + NameComposer composer = new NameComposer(capitalization, wordDelimiter, prefix, suffix); + return composer.compose(className); + } + + public static IFile createHeaderFile(IPath filePath, boolean force, IProgressMonitor monitor) + throws CoreException { return createEmptyFile(filePath, force, monitor); } - public static IFile createSourceFile(IPath filePath, boolean force, IProgressMonitor monitor) throws CoreException { + public static IFile createSourceFile(IPath filePath, boolean force, IProgressMonitor monitor) + throws CoreException { return createEmptyFile(filePath, force, monitor); } - public static IFile createEmptyFile(IPath filePath, boolean force, IProgressMonitor monitor) throws CoreException { + public static IFile createTestFile(IPath filePath, boolean force, IProgressMonitor monitor) + throws CoreException { + return createEmptyFile(filePath, force, monitor); + } + + public static IFile createEmptyFile(IPath filePath, boolean force, IProgressMonitor monitor) + throws CoreException { ByteArrayInputStream stream = new ByteArrayInputStream(new byte[0]); return createNewFile(filePath, stream, force, monitor); } - private static IFile createNewFile(IPath newFilePath, InputStream contents, boolean force, IProgressMonitor monitor) throws CoreException { + private static IFile createNewFile(IPath newFilePath, InputStream contents, boolean force, + IProgressMonitor monitor) throws CoreException { int totalWork = 100; int createFileWork = totalWork; @@ -122,7 +153,8 @@ public class NewSourceFileGenerator { return newFile; } - private static void createFile(IFile fileHandle, InputStream contents, boolean force, IProgressMonitor monitor) throws CoreException { + private static void createFile(IFile fileHandle, InputStream contents, boolean force, + IProgressMonitor monitor) throws CoreException { if (contents == null) contents = new ByteArrayInputStream(new byte[0]); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CodeGeneration.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CodeGeneration.java index 00f5e7e443e..10bdb306c96 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CodeGeneration.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CodeGeneration.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2001, 2008 IBM Corporation and others. + * Copyright (c) 2001, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * Rational Software - initial implementation * Anton Leherbauer (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.ui; @@ -18,7 +19,6 @@ import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.internal.corext.codemanipulation.StubUtility; - /** * Class that offers access to the templates contained in the 'Code Templates' preference page. * @@ -33,60 +33,229 @@ public class CodeGeneration { /** * Returns the content for a new header file using the default 'header file' code template. - * @param tu The translation unit to create the source for. The translation unit does not need to exist. - * @param typeComment The comment for the type to created. Used when the code template contains a ${typecomment} variable. Can be null if - * no comment should be added. + * @param tu The translation unit to create the source for. The translation unit does not need + * to exist. + * @param lineDelimiter The line delimiter to be used. + * @return Returns the new content or null if the template is undefined or empty. + * @throws CoreException + * @since 5.3 + */ + public static String getHeaderFileContent(Template template, ITranslationUnit tu, + String lineDelimiter) throws CoreException { + return getHeaderFileContent(template, tu, null, null, null, null, null, null, null, + lineDelimiter); + } + + /** + * Returns the content for a new header file using the default 'header file' code template. + * @param tu The translation unit to create the source for. The translation unit does not need + * to exist. + * @param typeComment The comment for the type to created. Used when the code template contains + * a ${typecomment} variable. Can be null if no comment should be added. * @param typeContent The code of the type, including type declaration and body. * @param lineDelimiter The line delimiter to be used. * @return Returns the new content or null if the template is undefined or empty. * @throws CoreException */ - public static String getHeaderFileContent(ITranslationUnit tu, String typeComment, String typeContent, String lineDelimiter) throws CoreException { - return StubUtility.getHeaderFileContent(tu, getFileComment(tu, lineDelimiter), typeComment, typeContent, lineDelimiter); + public static String getHeaderFileContent(ITranslationUnit tu, String typeComment, + String typeContent, String lineDelimiter) throws CoreException { + return getHeaderFileContent(tu, null, null, null, null, typeComment, typeContent, null, + lineDelimiter); } /** * Returns the content for a new header file using the default 'header file' code template. * @param template The file template to use or null for the default template - * @param tu The translation unit to create the source for. The translation unit does not need to exist. - * @param typeComment The comment for the type to created. Used when the code template contains a ${typecomment} variable. Can be null if - * no comment should be added. + * @param tu The translation unit to create the source for. The translation unit does not need + * to exist. + * @param typeComment The comment for the type to created. Used when the code template contains + * a ${typecomment} variable. Can be null if no comment should be added. * @param typeContent The code of the type, including type declaration and body. * @param lineDelimiter The line delimiter to be used. * @return Returns the new content or null if the template is undefined or empty. * @throws CoreException */ - public static String getHeaderFileContent(Template template, ITranslationUnit tu, String typeComment, String typeContent, String lineDelimiter) throws CoreException { - return StubUtility.getHeaderFileContent(template, tu, getFileComment(tu, lineDelimiter), typeComment, typeContent, lineDelimiter); + public static String getHeaderFileContent(Template template, ITranslationUnit tu, + String typeComment, String typeContent, String lineDelimiter) throws CoreException { + return getHeaderFileContent(template, tu, null, null, null, null, typeComment, typeContent, + null, lineDelimiter); + } + + /** + * Returns the content for a new header file using the default 'header file' code template. + * @param tu The translation unit to create the source for. The translation unit does not need + * to exist. + * @param includes Include statements, or {@code null} if there are no includes. + * @param namespaceBegin Beginning of namespace declarations, or {@code null} if there is no + * namespace. + * @param namespaceEnd End of namespace declarations, or {@code null} if there is no + * namespace. + * @param namespaceName Fully qualified namespace name, or {@code null} if there is no + * namespace. + * @param typeComment The comment for the type to created. Used when the code template contains + * a ${typecomment} variable. Can be null if no comment should be added. + * @param typeContent The code of the type, including type declaration and body. + * @param typeName The name of the type. + * @param lineDelimiter The line delimiter to be used. + * @return Returns the new content or null if the template is undefined or empty. + * @throws CoreException + * @since 5.3 + */ + public static String getHeaderFileContent(ITranslationUnit tu, String includes, + String namespaceBegin, String namespaceEnd, String namespaceName, String typeComment, + String typeContent, String typeName, String lineDelimiter) throws CoreException { + return StubUtility.getHeaderFileContent(tu, typeContent, + getFileComment(tu, lineDelimiter), includes, namespaceBegin, namespaceEnd, + namespaceName, typeComment, typeName, lineDelimiter); + } + + /** + * Returns the content for a new header file using the default 'header file' code template. + * @param template The file template to use or null for the default template + * @param tu The translation unit to create the source for. The translation unit does not need + * to exist. + * @param includes Include statements, or {@code null} if there are no includes. + * @param namespaceBegin Beginning of namespace declarations, or {@code null} if there is no + * namespace. + * @param namespaceEnd End of namespace declarations, or {@code null} if there is no + * namespace. + * @param namespaceName Fully qualified namespace name, or {@code null} if there is no + * namespace. + * @param typeComment The comment for the type to created. Used when the code template contains + * a ${typecomment} variable. Can be null if no comment should be added. + * @param typeContent The code of the type, including type declaration and body. + * @param typeName The name of the type. + * @param lineDelimiter The line delimiter to be used. + * @return Returns the new content or null if the template is undefined or empty. + * @throws CoreException + * @since 5.3 + */ + public static String getHeaderFileContent(Template template, ITranslationUnit tu, + String includes, String namespaceBegin, String namespaceEnd, String namespaceName, + String typeComment, String typeContent, String typeName, String lineDelimiter) + throws CoreException { + return StubUtility.getHeaderFileContent(template, tu, typeContent, + getFileComment(tu, lineDelimiter), includes, namespaceBegin, namespaceEnd, + namespaceName, typeComment, typeName, lineDelimiter); } /** * Returns the content for a new translation unit using the 'source file' code template. - * @param tu The translation unit to create the source for. The translation unit does not need to exist. - * @param typeComment The comment for the type to created. Used when the code template contains a ${typecomment} variable. Can be null if - * no comment should be added. + * @param tu The translation unit to create the source for. The translation unit does not need + * to exist. + * @param typeComment The comment for the type to created. Used when the code template contains + * a ${typecomment} variable. Can be null if no comment should be added. * @param typeContent The code of the type, including type declaration and body. * @param lineDelimiter The line delimiter to be used. * @return Returns the new content or null if the template is undefined or empty. * @throws CoreException */ - public static String getBodyFileContent(ITranslationUnit tu, String typeComment, String typeContent, String lineDelimiter) throws CoreException { - return StubUtility.getBodyFileContent(tu, getFileComment(tu, lineDelimiter), typeComment, typeContent, lineDelimiter); + public static String getBodyFileContent(ITranslationUnit tu, String typeComment, + String typeContent, String lineDelimiter) throws CoreException { + return getBodyFileContent(tu, typeContent, null, null, null, null, typeComment, null, + lineDelimiter); } /** * Returns the content for a new translation unit using the 'source file' code template. * @param template The file template to use or null for the default template - * @param tu The translation unit to create the source for. The translation unit does not need to exist. - * @param typeComment The comment for the type to created. Used when the code template contains a ${typecomment} variable. Can be null if - * no comment should be added. + * @param tu The translation unit to create the source for. The translation unit does not need + * to exist. + * @param typeComment The comment for the type to created. Used when the code template contains + * a ${typecomment} variable. Can be null if no comment should be added. * @param typeContent The code of the type, including type declaration and body. * @param lineDelimiter The line delimiter to be used. * @return Returns the new content or null if the template is undefined or empty. * @throws CoreException */ - public static String getBodyFileContent(Template template, ITranslationUnit tu, String typeComment, String typeContent, String lineDelimiter) throws CoreException { - return StubUtility.getBodyFileContent(template, tu, getFileComment(tu, lineDelimiter), typeComment, typeContent, lineDelimiter); + public static String getBodyFileContent(Template template, ITranslationUnit tu, + String typeComment, String typeContent, String lineDelimiter) throws CoreException { + return getBodyFileContent(template, tu, typeContent, null, null, null, null, typeComment, + null, lineDelimiter); + } + + /** + * Returns the content for a new source file using the default 'source file' code template. + * @param tu The translation unit to create the source for. The translation unit does not need + * to exist. + * @param includes Include statements, or {@code null} if there are no includes. + * @param namespaceBegin Beginning of namespace declarations, or {@code null} if there is no + * namespace. + * @param namespaceEnd End of namespace declarations, or {@code null} if there is no + * namespace. + * @param namespaceName Fully qualified namespace name, or {@code null} if there is no + * namespace. + * @param typeComment The comment for the type to created. Used when the code template contains + * a ${typecomment} variable. Can be null if no comment should be added. + * @param typeContent The code of the type, including type declaration and body. + * @param typeName The name of the type. + * @param lineDelimiter The line delimiter to be used. + * @return Returns the new content or null if the template is undefined or empty. + * @throws CoreException + * @since 5.3 + */ + public static String getBodyFileContent(ITranslationUnit tu, + String includes, String namespaceBegin, String namespaceEnd, String namespaceName, + String typeComment, String typeContent, String typeName, String lineDelimiter) + throws CoreException { + return StubUtility.getBodyFileContent(tu, typeContent, getFileComment(tu, lineDelimiter), + includes, namespaceBegin, namespaceEnd, namespaceName, typeComment, typeName, + lineDelimiter); + } + + /** + * Returns the content for a new source file using the default 'source file' code template. + * @param template The file template to use or null for the default template + * @param tu The translation unit to create the source for. The translation unit does not need + * to exist. + * @param includes Include statements, or {@code null} if there are no includes. + * @param namespaceBegin Beginning of namespace declarations, or {@code null} if there is no + * namespace. + * @param namespaceEnd End of namespace declarations, or {@code null} if there is no + * namespace. + * @param namespaceName Fully qualified namespace name, or {@code null} if there is no + * namespace. + * @param typeComment The comment for the type to created. Used when the code template contains + * a ${typecomment} variable. Can be null if no comment should be added. + * @param typeContent The code of the type, including type declaration and body. + * @param typeName The name of the type. + * @param lineDelimiter The line delimiter to be used. + * @return Returns the new content or null if the template is undefined or empty. + * @throws CoreException + * @since 5.3 + */ + public static String getBodyFileContent(Template template, ITranslationUnit tu, + String includes, String namespaceBegin, String namespaceEnd, String namespaceName, + String typeComment, String typeContent, String typeName, String lineDelimiter) + throws CoreException { + return StubUtility.getBodyFileContent(template, tu, typeContent, + getFileComment(tu, lineDelimiter), includes, namespaceBegin, namespaceEnd, + namespaceName, typeComment, typeName, lineDelimiter); + } + + /** + * Returns the content for a new translation unit using the 'test file' code template. + * @param tu The translation unit to create the source for. The translation unit does not need + * to exist. + * @param includes Include statements, or {@code null} if there are no includes. + * @param namespaceBegin Beginning of namespace declarations, or {@code null} if there is no + * namespace. + * @param namespaceEnd End of namespace declarations, or {@code null} if there is no + * namespace. + * @param namespaceName Fully qualified namespace name, or {@code null} if there is no + * namespace. + * @param testCases The test cases code. + * @param typeName The name of the type. + * @param lineDelimiter The line delimiter to be used. + * @return Returns the new content or null if the template is undefined or empty. + * @throws CoreException + * @since 5.3 + */ + public static String getTestFileContent(ITranslationUnit tu, + String includes, String namespaceBegin, String namespaceEnd, String namespaceName, + String testCases, String typeName, String lineDelimiter) throws CoreException { + return StubUtility.getTestFileContent(tu, testCases, getFileComment(tu, lineDelimiter), + includes, namespaceBegin, namespaceEnd, namespaceName, typeName, lineDelimiter); } /** @@ -103,8 +272,10 @@ public class CodeGeneration { * the comment code template is empty. The returned string is unformatted and and has no indent (formatting required). * @throws CoreException Thrown when the evaluation of the code template fails. */ - public static String getMethodBodyContent(ITranslationUnit tu, String typeName, String methodName, String bodyStatement, String lineDelimiter) throws CoreException { - return StubUtility.getMethodBodyContent(tu.getCProject(), typeName, methodName, bodyStatement, lineDelimiter); + public static String getMethodBodyContent(ITranslationUnit tu, String typeName, + String methodName, String bodyStatement, String lineDelimiter) throws CoreException { + return StubUtility.getMethodBodyContent(tu.getCProject(), typeName, methodName, + bodyStatement, lineDelimiter); } /** @@ -112,16 +283,20 @@ public class CodeGeneration { * null is returned if the template is empty. *

The returned string is unformatted and not indented. * - * @param tu The translation unit to which the method belongs. The translation unit does not need to exist. + * @param tu The translation unit to which the method belongs. The translation unit + * does not need to exist. * @param typeName Name of the type to which the constructor belongs. * @param bodyStatement The code to be entered at the place of the variable ${body_statement}. * @param lineDelimiter The line delimiter to be used. - * @return Returns the constructed body content or null if - * the comment code template is empty. The returned string is unformatted and and has no indent (formatting required). + * @return Returns the constructed body content or null if the comment code + * template is empty. The returned string is unformatted and and has no indent + * (formatting required). * @throws CoreException Thrown when the evaluation of the code template fails. */ - public static String getConstructorBodyContent(ITranslationUnit tu, String typeName, String bodyStatement, String lineDelimiter) throws CoreException { - return StubUtility.getConstructorBodyContent(tu.getCProject(), typeName, bodyStatement, lineDelimiter); + public static String getConstructorBodyContent(ITranslationUnit tu, String typeName, + String bodyStatement, String lineDelimiter) throws CoreException { + return StubUtility.getConstructorBodyContent(tu.getCProject(), typeName, bodyStatement, + lineDelimiter); } /** @@ -129,40 +304,116 @@ public class CodeGeneration { * null is returned if the template is empty. *

The returned string is unformatted and not indented. * - * @param tu The translation unit to which the method belongs. The translation unit does not need to exist. + * @param tu The translation unit to which the method belongs. The translation unit + * does not need to exist. * @param typeName Name of the type to which the constructor belongs. * @param bodyStatement The code to be entered at the place of the variable ${body_statement}. * @param lineDelimiter The line delimiter to be used. - * @return Returns the constructed body content or null if - * the comment code template is empty. The returned string is unformatted and and has no indent (formatting required). + * @return Returns the constructed body content or null if the comment code + * template is empty. The returned string is unformatted and and has no indent + * (formatting required). * @throws CoreException Thrown when the evaluation of the code template fails. */ - public static String getDestructorBodyContent(ITranslationUnit tu, String typeName, String bodyStatement, String lineDelimiter) throws CoreException { - return StubUtility.getDestructorBodyContent(tu.getCProject(), typeName, bodyStatement, lineDelimiter); + public static String getDestructorBodyContent(ITranslationUnit tu, String typeName, + String bodyStatement, String lineDelimiter) throws CoreException { + return StubUtility.getDestructorBodyContent(tu.getCProject(), typeName, bodyStatement, + lineDelimiter); } /** - * Returns the content for a new file comment using the 'file comment' code template. The returned content is unformatted and is not indented. - * @param tu The translation unit to add the comment to. The translation unit does not need to exist. + * Returns the content of the class definition body using the class body template. + * null is returned if the template is empty. + *

The returned string is unformatted and not indented. + * + * @param tu The translation unit to which the method belongs. The translation unit + * does not need to exist. + * @param className The name of the class. + * @param classMemberDeclarations The code to be entered at the place of the variable + * ${declarations}. * @param lineDelimiter The line delimiter to be used. - * @return Returns the new content or null if the code template is undefined or empty. The returned content is unformatted and is not indented. + * @return Returns the constructed class body content or null if + * the class body code template is empty. The returned string is unformatted and + * has no indent (formatting required). + * @throws CoreException Thrown when the evaluation of the code template fails. + * @since 5.3 + */ + public static String getClassBodyContent(ITranslationUnit tu, String className, + String classMemberDeclarations, String lineDelimiter) + throws CoreException { + return StubUtility.getClassBodyContent(tu.getCProject(), className, classMemberDeclarations, + lineDelimiter); + } + + /** + * Returns the content of the beginning of a namespace declaration using the corresponding + * template. null is returned if the template is empty. + *

The returned string is unformatted and not indented. + * + * @param tu The translation unit to which the method belongs. The translation unit + * does not need to exist. + * @param namespaceName The name of the namespace. + * @param lineDelimiter The line delimiter to be used. + * @return Returns the constructed beginning of a namespace declaration,or null if + * the namespace code template is empty. The returned string is unformatted and has no + * indent (formatting required). + * @throws CoreException Thrown when the evaluation of the code template fails. + * @since 5.3 + */ + public static String getNamespaceBeginContent(ITranslationUnit tu, String namespaceName, + String lineDelimiter) throws CoreException { + return StubUtility.getNamespaceBeginContent(tu.getCProject(), namespaceName, lineDelimiter); + } + + /** + * Returns the content of the end of a namespace declaration using the corresponding + * template. null is returned if the template is empty. + *

The returned string is unformatted and not indented. + * + * @param tu The translation unit to which the method belongs. The translation unit + * does not need to exist. + * @param namespaceName The name of the namespace. + * @param lineDelimiter The line delimiter to be used. + * @return Returns the constructed end of a namespace declaration,or null if + * the namespace code template is empty. The returned string is unformatted and has no + * indent (formatting required). + * @throws CoreException Thrown when the evaluation of the code template fails. + * @since 5.3 + */ + public static String getNamespaceEndContent(ITranslationUnit tu, String namespaceName, + String lineDelimiter) throws CoreException { + return StubUtility.getNamespaceEndContent(tu.getCProject(), namespaceName, lineDelimiter); + } + + /** + * Returns the content for a new file comment using the 'file comment' code template. + * The returned content is unformatted and is not indented. + * @param tu The translation unit to add the comment to. The translation unit does not need + * to exist. + * @param lineDelimiter The line delimiter to be used. + * @return Returns the new content or null if the code template is undefined + * or empty. The returned content is unformatted and is not indented. * @throws CoreException Thrown when the evaluation of the code template fails. * @since 5.0 */ - public static String getFileComment(ITranslationUnit tu, String lineDelimiter) throws CoreException { + public static String getFileComment(ITranslationUnit tu, String lineDelimiter) + throws CoreException { return StubUtility.getFileComment(tu, lineDelimiter); } /** - * Returns the content for a new type comment using the 'typecomment' code template. The returned content is unformatted and is not indented. - * @param tu The translation unit where the type is contained. The translation unit does not need to exist. - * @param typeQualifiedName The name of the type to which the comment is added. For inner types the name must be qualified and include the outer - * types names (dot separated). + * Returns the content for a new type comment using the 'typecomment' code template. + * The returned content is unformatted and is not indented. + * @param tu The translation unit where the type is contained. The translation unit + * does not need to exist. + * @param typeQualifiedName The name of the type to which the comment is added. For inner types + * the name must be qualified and include the outer types names (dot separated). * @param lineDelimiter The line delimiter to be used. - * @return Returns the new content or null if the code template is undefined or empty. The returned content is unformatted and is not indented. + * @return Returns the new content or null if the code template is undefined + * or empty. The returned content is unformatted and is not indented. * @throws CoreException */ - public static String getClassComment(ITranslationUnit tu, String typeQualifiedName, String lineDelimiter) throws CoreException { + public static String getClassComment(ITranslationUnit tu, String typeQualifiedName, + String lineDelimiter) throws CoreException { return StubUtility.getClassComment(tu, typeQualifiedName, lineDelimiter); } @@ -171,19 +422,23 @@ public class CodeGeneration { * null is returned if the template is empty. *

The returned string is unformatted and not indented. * - * @param tu The translation unit to which the method belongs. The translation unit does not need to exist. + * @param tu The translation unit to which the method belongs. The translation unit + * does not need to exist. * @param declaringTypeName Name of the type to which the method belongs. * @param methodName Name of the method. * @param paramNames Names of the parameters for the method. * @param excTypeSig Thrown exceptions. * @param retTypeSig Return type. * @param lineDelimiter The line delimiter to be used. - * @return Returns the constructed comment or null if - * the comment code template is empty. The returned content is unformatted and not indented (formatting required). + * @return Returns the constructed comment or null if the comment code template + * is empty. The returned content is unformatted and not indented (formatting required). * @throws CoreException Thrown when the evaluation of the code template fails. */ - public static String getMethodComment(ITranslationUnit tu, String declaringTypeName, String methodName, String[] paramNames, String[] excTypeSig, String retTypeSig, String lineDelimiter) throws CoreException { - return StubUtility.getMethodComment(tu, declaringTypeName, methodName, paramNames, excTypeSig, retTypeSig, lineDelimiter); + public static String getMethodComment(ITranslationUnit tu, String declaringTypeName, + String methodName, String[] paramNames, String[] excTypeSig, String retTypeSig, + String lineDelimiter) throws CoreException { + return StubUtility.getMethodComment(tu, declaringTypeName, methodName, paramNames, + excTypeSig, retTypeSig, lineDelimiter); } /** @@ -191,17 +446,20 @@ public class CodeGeneration { * null is returned if the template is empty. *

The returned string is unformatted and not indented. * - * @param tu The translation unit to which the method belongs. The translation unit does not need to exist. + * @param tu The translation unit to which the method belongs. The translation unit + * does not need to exist. * @param declaringTypeName Name of the type to which the method belongs. * @param paramNames Names of the parameters for the method. * @param excTypeSig Thrown exceptions. * @param lineDelimiter The line delimiter to be used. - * @return Returns the constructed comment or null if - * the comment code template is empty. The returned content is unformatted and not indented (formatting required). + * @return Returns the constructed comment or null if the comment code template + * is empty. The returned content is unformatted and not indented (formatting required). * @throws CoreException Thrown when the evaluation of the code template fails. */ - public static String getConstructorComment(ITranslationUnit tu, String declaringTypeName, String[] paramNames, String[] excTypeSig, String lineDelimiter) throws CoreException { - return StubUtility.getConstructorComment(tu, declaringTypeName, paramNames, excTypeSig, lineDelimiter); + public static String getConstructorComment(ITranslationUnit tu, String declaringTypeName, + String[] paramNames, String[] excTypeSig, String lineDelimiter) throws CoreException { + return StubUtility.getConstructorComment(tu, declaringTypeName, paramNames, excTypeSig, + lineDelimiter); } /** @@ -209,16 +467,17 @@ public class CodeGeneration { * null is returned if the template is empty. *

The returned string is unformatted and not indented. * - * @param tu The translation unit to which the method belongs. The translation unit does not need to exist. + * @param tu The translation unit to which the method belongs. The translation unit + * does not need to exist. * @param declaringTypeName Name of the type to which the method belongs. * @param excTypeSig Thrown exceptions. * @param lineDelimiter The line delimiter to be used. - * @return Returns the constructed comment or null if - * the comment code template is empty. The returned content is unformatted and not indented (formatting required). + * @return Returns the constructed comment or null if the comment code template + * is empty. The returned content is unformatted and not indented (formatting required). * @throws CoreException Thrown when the evaluation of the code template fails. */ - public static String getDestructorComment(ITranslationUnit tu, String declaringTypeName, String[] excTypeSig, String lineDelimiter) throws CoreException { + public static String getDestructorComment(ITranslationUnit tu, String declaringTypeName, + String[] excTypeSig, String lineDelimiter) throws CoreException { return StubUtility.getDestructorComment(tu, declaringTypeName, excTypeSig, lineDelimiter); } - } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewClassCreationWizardPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewClassCreationWizardPage.java index 364c948afca..f57fb9261cb 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewClassCreationWizardPage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewClassCreationWizardPage.java @@ -9,6 +9,7 @@ * QNX Software Systems - initial API and implementation * IBM Corporation * Warren Paul (Nokia) - 174238 + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.ui.wizards; @@ -29,6 +30,7 @@ import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.viewers.ISelection; @@ -105,10 +107,18 @@ import org.eclipse.cdt.internal.ui.wizards.dialogfields.StringDialogField; import org.eclipse.cdt.internal.ui.wizards.filewizard.NewSourceFileGenerator; public class NewClassCreationWizardPage extends NewElementWizardPage { - protected final static String PAGE_NAME = "NewClassWizardPage"; //$NON-NLS-1$ + protected static final String PAGE_NAME = "NewClassWizardPage"; //$NON-NLS-1$ protected static final int MAX_FIELD_CHARS = 50; - - // field IDs + + // Dialog setting keys. + private static final String KEY_NAMESPACE_SELECTED = "namespaceSelected"; //$NON-NLS-1$ + private static final String KEY_NAMESPACE = "namespace"; //$NON-NLS-1$ + private static final String KEY_TEST_FILE_SELECTED = "testFileSelected"; //$NON-NLS-1$ + private static final String KEY_STUB_SELECTED = "stubSelected"; //$NON-NLS-1$ + private static final String KEY_STUB_VIRTUAL = "stubVirtual"; //$NON-NLS-1$ + private static final String KEY_STUB_INLINE = "stubInline"; //$NON-NLS-1$ + + // Field IDs protected static final int SOURCE_FOLDER_ID = 1; protected static final int NAMESPACE_ID = 2; protected static final int CLASS_NAME_ID = 4; @@ -116,9 +126,11 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { protected static final int METHOD_STUBS_ID = 16; protected static final int HEADER_FILE_ID = 32; protected static final int SOURCE_FILE_ID = 64; + /** @since 5.3 */ + protected static final int TEST_FILE_ID = 128; protected static final int ALL_FIELDS = SOURCE_FOLDER_ID | NAMESPACE_ID | CLASS_NAME_ID | BASE_CLASSES_ID | METHOD_STUBS_ID - | HEADER_FILE_ID | SOURCE_FILE_ID; + | HEADER_FILE_ID | SOURCE_FILE_ID | TEST_FILE_ID; protected int fLastFocusedField = 0; protected StringButtonDialogField fSourceFolderDialogField; @@ -127,9 +139,18 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { protected StringDialogField fClassNameDialogField; protected BaseClassesListDialogField fBaseClassesDialogField; protected MethodStubsListDialogField fMethodStubsDialogField; - protected SelectionButtonDialogField fUseDefaultSelection; protected StringButtonDialogField fHeaderFileDialogField; - protected StringButtonDialogField fSourceFileDialogField; + protected StringButtonDialogField fSourceFileDialogField; + /** @since 5.3 */ + protected StringButtonDialogField fTestFileDialogField; + /** @since 5.3 */ + protected SelectionButtonDialogField fTestFileSelection; + /** @since 5.3 */ + protected boolean fHeaderFileDerivedFromClassName; + /** @since 5.3 */ + protected boolean fSourceFileDerivedFromClassName; + /** @since 5.3 */ + protected boolean fTestFileDerivedFromClassName; protected IStatus fSourceFolderStatus; protected IStatus fNamespaceStatus; @@ -138,10 +159,14 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { protected IStatus fMethodStubsStatus; protected IStatus fHeaderFileStatus; protected IStatus fSourceFileStatus; + /** @since 5.3 */ + protected IStatus fTestFileStatus; protected final IStatus STATUS_OK = new StatusInfo(); - protected IFile fCreatedSourceFile; protected IFile fCreatedHeaderFile; + protected IFile fCreatedSourceFile; + /** @since 5.3 */ + protected IFile fCreatedTestFile; protected ICElement fCreatedClass; /** @@ -150,13 +175,6 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { * created. */ private boolean isFirstTime = false; - /** - * the default method stubs - */ - protected static final IMethodStub[] DEFAULT_METHOD_STUBS = { - new ConstructorMethodStub(), - new DestructorMethodStub() - }; /** @@ -194,9 +212,6 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { fMethodStubsDialogField = new MethodStubsListDialogField(NewClassWizardMessages.NewClassCreationWizardPage_methodStubs_label, methodStubsAdapter); FileGroupFieldAdapter fileGroupAdapter = new FileGroupFieldAdapter(); - fUseDefaultSelection = new SelectionButtonDialogField(SWT.CHECK); - fUseDefaultSelection.setDialogFieldListener(fileGroupAdapter); - fUseDefaultSelection.setLabelText(NewClassWizardMessages.NewClassCreationWizardPage_useDefaultLocation_label); fHeaderFileDialogField = new StringButtonDialogField(fileGroupAdapter); fHeaderFileDialogField.setDialogFieldListener(fileGroupAdapter); fHeaderFileDialogField.setLabelText(NewClassWizardMessages.NewClassCreationWizardPage_headerFile_label); @@ -205,7 +220,17 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { fSourceFileDialogField.setDialogFieldListener(fileGroupAdapter); fSourceFileDialogField.setLabelText(NewClassWizardMessages.NewClassCreationWizardPage_sourceFile_label); fSourceFileDialogField.setButtonLabel(NewClassWizardMessages.NewClassCreationWizardPage_sourceFile_button); - + fTestFileSelection = new SelectionButtonDialogField(SWT.CHECK); + fTestFileSelection.setDialogFieldListener(fileGroupAdapter); + fTestFileSelection.setLabelText(NewClassWizardMessages.NewClassCreationWizardPage_testFile_label); + fTestFileDialogField = new StringButtonDialogField(fileGroupAdapter); + fTestFileDialogField.setDialogFieldListener(fileGroupAdapter); + fTestFileDialogField.setButtonLabel(NewClassWizardMessages.NewClassCreationWizardPage_testFile_button); + + fHeaderFileDerivedFromClassName = true; + fSourceFileDerivedFromClassName = true; + fTestFileDerivedFromClassName = true; + fSourceFolderStatus = STATUS_OK; fNamespaceStatus = STATUS_OK; fClassNameStatus = STATUS_OK; @@ -213,12 +238,10 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { fMethodStubsStatus = STATUS_OK; fHeaderFileStatus = STATUS_OK; fSourceFileStatus = STATUS_OK; + fTestFileStatus = STATUS_OK; fLastFocusedField = 0; isFirstTime = true; - - updateNamespaceEnableState(); - updateFileGroupEnableState(); } // -------- UI Creation --------- @@ -339,10 +362,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { protected void createBaseClassesControls(Composite composite, int nColumns) { fBaseClassesDialogField.doFillIntoGrid(composite, nColumns); Control listControl = fBaseClassesDialogField.getListControl(null); - GridData gd = (GridData) listControl.getLayoutData(); - gd.heightHint = convertHeightInCharsToPixels(5); - gd.grabExcessVerticalSpace = false; - gd.widthHint = getMaxFieldWidth(); + LayoutUtil.setVerticalGrabbing(listControl, false); listControl.addFocusListener(new StatusFocusListener(BASE_CLASSES_ID)); } @@ -356,53 +376,46 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { protected void createMethodStubsControls(Composite composite, int nColumns) { fMethodStubsDialogField.doFillIntoGrid(composite, nColumns); Control listControl = fMethodStubsDialogField.getListControl(null); - GridData gd = (GridData) listControl.getLayoutData(); - gd.heightHint = convertHeightInCharsToPixels(5); - gd.grabExcessVerticalSpace = false; - gd.widthHint = getMaxFieldWidth(); + LayoutUtil.setHeightHint(listControl, + convertHeightInCharsToPixels(6) + convertHeightInCharsToPixels(1) / 2); + LayoutUtil.setVerticalGrabbing(listControl, false); listControl.addFocusListener(new StatusFocusListener(METHOD_STUBS_ID)); } /** - * Creates the controls for the file name fields. Expects a GridLayout with at - * least 4 columns. + * Creates the controls for the file name fields. Expects a GridLayout with + * at least 4 columns. * * @param composite the parent composite * @param nColumns number of columns to span */ protected void createFileControls(Composite composite, int nColumns) { + fHeaderFileDialogField.doFillIntoGrid(composite, nColumns); + Text textControl = fHeaderFileDialogField.getTextControl(null); + LayoutUtil.setWidthHint(textControl, getMaxFieldWidth()); + textControl.addFocusListener(new StatusFocusListener(HEADER_FILE_ID)); + + fSourceFileDialogField.doFillIntoGrid(composite, nColumns); + textControl = fSourceFileDialogField.getTextControl(null); + LayoutUtil.setWidthHint(textControl, getMaxFieldWidth()); + textControl.addFocusListener(new StatusFocusListener(SOURCE_FILE_ID)); + Composite tabGroup = new Composite(composite, SWT.NONE); GridLayout layout = new GridLayout(); layout.marginWidth = 0; layout.marginHeight = 0; tabGroup.setLayout(layout); - fUseDefaultSelection.doFillIntoGrid(tabGroup, 1); + fTestFileSelection.doFillIntoGrid(tabGroup, 1); - LayoutUtil.setHorizontalSpan(fHeaderFileDialogField.getLabelControl(composite), 1); - Text textControl = fHeaderFileDialogField.getTextControl(composite); + textControl = fTestFileDialogField.getTextControl(composite); GridData gd = new GridData(GridData.FILL_HORIZONTAL); gd.widthHint = getMaxFieldWidth(); - gd.horizontalSpan = 1; + gd.horizontalSpan = 2; textControl.setLayoutData(gd); - textControl.addFocusListener(new StatusFocusListener(HEADER_FILE_ID)); + textControl.addFocusListener(new StatusFocusListener(TEST_FILE_ID)); - Button button = fHeaderFileDialogField.getChangeControl(composite); - gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); - gd.widthHint = SWTUtil.getButtonWidthHint(button); - button.setLayoutData(gd); - - DialogField.createEmptySpace(composite, 1); - - LayoutUtil.setHorizontalSpan(fSourceFileDialogField.getLabelControl(composite), 1); - textControl = fSourceFileDialogField.getTextControl(composite); - gd = new GridData(GridData.FILL_HORIZONTAL); - gd.widthHint = getMaxFieldWidth(); - gd.horizontalSpan = 1; - textControl.setLayoutData(gd); - textControl.addFocusListener(new StatusFocusListener(SOURCE_FILE_ID)); - - button = fSourceFileDialogField.getChangeControl(composite); + Button button = fTestFileDialogField.getChangeControl(composite); gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); gd.widthHint = SWTUtil.getButtonWidthHint(button); button.setLayoutData(gd); @@ -416,7 +429,14 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { * @param selection used to initialize the fields */ public void init(IStructuredSelection selection) { - ICElement celem = getInitialCElement(selection); + if (fDialogSettings == null) { + fDialogSettings = getDialogSettings().getSection(PAGE_NAME); + if (fDialogSettings == null) { + fDialogSettings = getDialogSettings().addNewSection(PAGE_NAME); + } + } + + ICElement celem = getInitialCElement(selection); String namespace = null; if (celem != null) { @@ -428,8 +448,13 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { } } } + if (namespace == null) { + namespace = fDialogSettings.get(KEY_NAMESPACE); + } + setNamespaceText(namespace, false); - setNamespaceSelection(namespace != null, true); + setNamespaceSelection(namespace != null || fDialogSettings.getBoolean(KEY_NAMESPACE_SELECTED), + true); IPath folderPath = null; if (celem != null) { @@ -450,8 +475,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { ITextSelection textSel = getEditorTextSelection(); if (textSel != null) { String text = textSel.getText(); - if (text != null && text.length() > 0 && - CConventions.validateClassName(text).isOK()) { + if (text != null && text.length() > 0 && CConventions.validateClassName(text).isOK()) { className = text; } } @@ -459,19 +483,28 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { IMethodStub[] stubs = getDefaultMethodStubs(); for (int i = 0; i < stubs.length; ++i) { - addMethodStub(stubs[i], true); + IMethodStub stub = stubs[i]; + if (stub.canModifyVirtual()) { + stub.setVirtual(getBooleanSettingWithDefault(KEY_STUB_VIRTUAL + i, stub.isVirtual())); + } + if (stub.canModifyInline()) { + stub.setInline(getBooleanSettingWithDefault(KEY_STUB_INLINE + i, stub.isInline())); + } + addMethodStub(stub, getBooleanSettingWithDefault(KEY_STUB_SELECTED + i, true)); } - //TODO restore dialog settings for method stubs? - // IDialogSettings section = getDialogSettings().getSection(PAGE_NAME); - // if (section != null) { - // enabled = section.getBoolean(stubName); - // } - setUseDefaultSelection(true, true); - + setTestFileSelection(fDialogSettings.getBoolean(KEY_TEST_FILE_SELECTED), true); handleFieldChanged(ALL_FIELDS); } - + + private boolean getBooleanSettingWithDefault(String key, boolean defaultValue) { + String value = fDialogSettings.get(key); + if (value == null) { + return defaultValue; + } + return Boolean.valueOf(value); + } + /** * Attempts to extract a C Element from the initial selection. * @@ -537,7 +570,10 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { * @return array of method stubs */ protected IMethodStub[] getDefaultMethodStubs() { - return DEFAULT_METHOD_STUBS; + return new IMethodStub[] { + new ConstructorMethodStub(), + new DestructorMethodStub() + }; } /** @@ -546,7 +582,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { * @return the source folder */ public String getSourceFolderText() { - return fSourceFolderDialogField.getText(); + return fSourceFolderDialogField.getText().trim(); } /** @@ -610,7 +646,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { * @return the namespace */ public String getNamespaceText() { - return fNamespaceDialogField.getText(); + return fNamespaceDialogField.getText().trim(); } /** @@ -661,7 +697,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { * @return the class name */ public String getClassName() { - return fClassNameDialogField.getText(); + return fClassNameDialogField.getText().trim(); } /** @@ -732,34 +768,24 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { } /** - * Returns the selection state of the file group checkbox. - * - * @return the selection state of the file group checkbox - */ - public boolean isUseDefaultSelected() { - return fUseDefaultSelection.isSelected(); - } - - /** - * Sets the use default checkbox's selection state. + * Sets the use test file creation checkbox's selection state. * * @param isSelected the checkbox's selection state * @param canBeModified if true the checkbox is * modifiable; otherwise it is read-only. + * @since 5.3 */ - public void setUseDefaultSelection(boolean isSelected, boolean canBeModified) { - fUseDefaultSelection.setSelection(isSelected); - fUseDefaultSelection.setEnabled(canBeModified); - updateFileGroupEnableState(); + public void setTestFileSelection(boolean isSelected, boolean canBeModified) { + fTestFileSelection.setSelection(isSelected); + fTestFileSelection.setEnabled(canBeModified); + updateTestFileEnableState(); } /** - * Updates the enable state of buttons related to the use default checkbox. + * Updates the enable state of test file name text box. */ - private void updateFileGroupEnableState() { - boolean filegroup = !isUseDefaultSelected(); - fHeaderFileDialogField.setEnabled(filegroup); - fSourceFileDialogField.setEnabled(filegroup); + private void updateTestFileEnableState() { + fTestFileDialogField.setEnabled(fTestFileSelection.isSelected()); } /** @@ -768,7 +794,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { * @return the header file */ public String getHeaderFileText() { - return fHeaderFileDialogField.getText(); + return fHeaderFileDialogField.getText().trim(); } /** @@ -778,29 +804,16 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { * @param update true if the dialog should be updated */ public void setHeaderFileText(String header, boolean update) { - fHeaderFileDialogField.setTextWithoutUpdate(header != null ? header : ""); //$NON-NLS-1$ - if (update) { - fHeaderFileDialogField.dialogFieldChanged(); - } + setFileText(fHeaderFileDialogField, header, update); } - + /** * Returns the current header file as a path. * * @return the header file path */ protected IPath getHeaderFileFullPath() { - String str = getHeaderFileText(); - IPath path = null; - if (str.length() > 0) { - path = new Path(str); - if (!path.isAbsolute()) { - IPath folderPath = getSourceFolderFullPath(); - if (folderPath != null) - path = folderPath.append(path); - } - } - return path; + return getFilePath(getHeaderFileText()); } /** @@ -810,27 +823,16 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { * @param update true if the dialog should be updated */ protected void setHeaderFileFullPath(IPath path, boolean update) { - String str = null; - if (path != null) { - IPath sourceFolder = getSourceFolderFullPath(); - if (sourceFolder != null) { - IPath relativePath = PathUtil.makeRelativePath(path, sourceFolder); - if (relativePath != null) - path = relativePath; - } - str = path.makeRelative().toString(); - } - setHeaderFileText(str, update); + setFileFullPath(fHeaderFileDialogField, path, update); } - /** * Returns the text entered into the source file input field. * * @return the source file */ public String getSourceFileText() { - return fSourceFileDialogField.getText(); + return fSourceFileDialogField.getText().trim(); } /** @@ -840,10 +842,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { * @param update true if the dialog should be updated */ public void setSourceFileText(String source, boolean update) { - fSourceFileDialogField.setTextWithoutUpdate(source != null ? source : ""); //$NON-NLS-1$ - if (update) { - fSourceFileDialogField.dialogFieldChanged(); - } + setFileText(fSourceFileDialogField, source, update); } /** @@ -852,17 +851,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { * @return the source file path */ protected IPath getSourceFileFullPath() { - String str = getSourceFileText(); - IPath path = null; - if (str.length() > 0) { - path = new Path(str); - if (!path.isAbsolute()) { - IPath folderPath = getSourceFolderFullPath(); - if (folderPath != null) - path = folderPath.append(path); - } - } - return path; + return getFilePath(getSourceFileText()); } /** @@ -872,6 +861,80 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { * @param update true if the dialog should be updated */ protected void setSourceFileFullPath(IPath path, boolean update) { + setFileFullPath(fSourceFileDialogField, path, update); + } + + /** + * Returns the text entered into the source file input field. + * + * @return the source file + * @since 5.3 + */ + public String getTestFileText() { + return fTestFileDialogField.isEnabled() ? fTestFileDialogField.getText().trim() : null; + } + + /** + * Sets the text of the test file input field. + * + * @param testFile the test file name + * @param update true if the dialog should be updated + * @since 5.3 + */ + public void setTestFileText(String testFile, boolean update) { + setFileText(fTestFileDialogField, testFile, update); + } + + /** + * Returns the current test file as a path. Returns {@code null} if creation of test file + * is disabled. + * + * @return the test file path, or {@code null} if creation of test file is disabled. + * @since 5.3 + */ + protected IPath getTestFileFullPath() { + return getFilePath(getTestFileText()); + } + + /** + * Returns a path corresponding to a file name. + * @param filename the name of a header, a source, or a test file. Can be {@code null}. + * @return the corresponding path, or {@code null} if the filename is {@code null}. + */ + private IPath getFilePath(String filename) { + if (filename == null || filename.length() == 0) { + return null; + } + IPath path = new Path(filename); + if (!path.isAbsolute()) { + IPath folderPath = getSourceFolderFullPath(); + if (folderPath != null) + path = folderPath.append(path); + } + return path; + } + + /** + * Sets a file name field to a given value. + * + * @param field the field to set + * @param filename the new value of the field + * @param update true if the dialog should be updated + */ + private void setFileText(StringButtonDialogField field, String filename, boolean update) { + field.setTextWithoutUpdate(filename != null ? filename : ""); //$NON-NLS-1$ + if (update) { + field.dialogFieldChanged(); + } + } + + /** + * Sets a file name field from the given path. + * + * @param path the file path + * @param update true if the dialog should be updated + */ + private void setFileFullPath(StringButtonDialogField field, IPath path, boolean update) { String str = null; if (path != null) { IPath sourceFolder = getSourceFolderFullPath(); @@ -882,9 +945,20 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { } str = path.makeRelative().toString(); } - setSourceFileText(str, update); + setFileText(field, str, update); } - + + /** + * Sets the test file from the given path. + * + * @param path the test file path + * @param update true if the dialog should be updated + * @since 5.3 + */ + protected void setTestFileFullPath(IPath path, boolean update) { + setFileFullPath(fTestFileDialogField, path, update); + } + /* * @see WizardPage#becomesVisible */ @@ -919,7 +993,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { public void focusGained(FocusEvent e) { if (fLastFocusedField != this.fieldID) { fLastFocusedField = this.fieldID; - if( isFirstTime ) { + if (isFirstTime) { isFirstTime = false; return; } @@ -946,19 +1020,17 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { IPath headerPath = getHeaderFileFullPath(); IPath sourcePath = getSourceFileFullPath(); setSourceFolderFullPath(newFolderPath, false); - if (!isUseDefaultSelected()) { - if (oldFolderPath != null && oldFolderPath.matchingFirstSegments(newFolderPath) == 0) { - if (headerPath != null) { - headerPath = newFolderPath.append(headerPath.lastSegment()); - } - if (sourcePath != null) { - sourcePath = newFolderPath.append(sourcePath.lastSegment()); - } - } - // adjust the relative paths - setHeaderFileFullPath(headerPath, false); - setSourceFileFullPath(sourcePath, false); - } + if (oldFolderPath != null && oldFolderPath.matchingFirstSegments(newFolderPath) == 0) { + if (headerPath != null) { + headerPath = newFolderPath.append(headerPath.lastSegment()); + } + if (sourcePath != null) { + sourcePath = newFolderPath.append(sourcePath.lastSegment()); + } + } + // adjust the relative paths + setHeaderFileFullPath(headerPath, false); + setSourceFileFullPath(sourcePath, false); handleFieldChanged(SOURCE_FOLDER_ID|ALL_FIELDS); } } @@ -1009,13 +1081,15 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { if (oldFolderPath == null) { IPath headerPath = getHeaderFileFullPath(); IPath sourcePath = getSourceFileFullPath(); + IPath testPath = getTestFileFullPath(); IPath newFolderPath = updateSourceFolderFromPath(ns.getEnclosingProject().getProject().getFullPath()); if (newFolderPath != null) { - changedFields |= SOURCE_FOLDER_ID | HEADER_FILE_ID | SOURCE_FILE_ID; + changedFields |= SOURCE_FOLDER_ID | HEADER_FILE_ID | SOURCE_FILE_ID | TEST_FILE_ID; setSourceFolderFullPath(newFolderPath, false); - // adjust the relative paths + // Adjust the relative paths setHeaderFileFullPath(headerPath, false); setSourceFileFullPath(sourcePath, false); + setTestFileFullPath(testPath, false); } } setNamespaceText(ns.getQualifiedTypeName().toString(), false); @@ -1074,21 +1148,19 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { } /** - * handles changes to the class name field + * Handles changes to the class name field */ private final class ClassNameFieldAdapter implements IDialogFieldListener { public void dialogFieldChanged(DialogField field) { int changedFields = CLASS_NAME_ID; - if (isUseDefaultSelected()) { - updateFilesFromClassName(fClassNameDialogField.getText()); - changedFields |= (HEADER_FILE_ID|SOURCE_FILE_ID); - } + updateFilesFromClassName(fClassNameDialogField.getText().trim()); + changedFields |= HEADER_FILE_ID | SOURCE_FILE_ID | TEST_FILE_ID; handleFieldChanged(changedFields); } } /** - * handles changes to the base classes field + * Handles changes to the base classes field */ private final class BaseClassesFieldAdapter implements IListAdapter { public void customButtonPressed(ListDialogField field, int index) { @@ -1152,37 +1224,50 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { IPath filePath = null; IPath headerPath = getHeaderFileFullPath(); IPath sourcePath = getSourceFileFullPath(); + IPath testPath = getTestFileFullPath(); if (field == fHeaderFileDialogField) { - filePath = chooseHeaderFile(); + filePath = chooseFile(NewClassWizardMessages.NewClassCreationWizardPage_ChooseHeaderFileDialog_title, + getHeaderFileFullPath()); if (filePath != null) { headerPath = filePath; } } else if (field == fSourceFileDialogField) { - filePath = chooseSourceFile(); + filePath = chooseFile(NewClassWizardMessages.NewClassCreationWizardPage_ChooseSourceFileDialog_title, + getSourceFileFullPath()); if (filePath != null) { sourcePath = filePath; } + } else if (field == fTestFileDialogField) { + filePath = chooseFile(NewClassWizardMessages.NewClassCreationWizardPage_ChooseTestFileDialog_title, + getTestFileFullPath()); + if (filePath != null) { + testPath = filePath; + } } if (filePath != null) { IPath folderPath = null; int changedFields = 0; int headerSegments = 0; int sourceSegments = 0; + int testSegments = 0; if (headerPath != null) headerSegments = filePath.matchingFirstSegments(headerPath); if (sourcePath != null) sourceSegments = filePath.matchingFirstSegments(sourcePath); - int segments = Math.min(headerSegments, sourceSegments); + if (testPath != null) + testSegments = filePath.matchingFirstSegments(testPath); + int segments = Math.min(Math.min(headerSegments, sourceSegments), testSegments); if (segments > 0) { IPath newFolderPath = filePath.uptoSegment(segments); folderPath = updateSourceFolderFromPath(newFolderPath); } if (folderPath != null) { - changedFields |= SOURCE_FOLDER_ID | HEADER_FILE_ID | SOURCE_FILE_ID; - // adjust the relative paths + changedFields |= SOURCE_FOLDER_ID | HEADER_FILE_ID | SOURCE_FILE_ID | TEST_FILE_ID; + // Adjust the relative paths setSourceFolderFullPath(folderPath, false); setHeaderFileFullPath(headerPath, false); setSourceFileFullPath(sourcePath, false); + setTestFileFullPath(testPath, false); } if (field == fHeaderFileDialogField) { setHeaderFileFullPath(filePath, false); @@ -1190,6 +1275,9 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { } else if (field == fSourceFileDialogField) { setSourceFileFullPath(filePath, false); changedFields |= SOURCE_FILE_ID; + } else if (field == fTestFileDialogField) { + setTestFileFullPath(filePath, false); + changedFields |= TEST_FILE_ID; } handleFieldChanged(changedFields); } @@ -1197,36 +1285,43 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { public void dialogFieldChanged(DialogField field) { int changedFields = 0; - if (field == fUseDefaultSelection) { - boolean enabled = !isUseDefaultSelected(); - fHeaderFileDialogField.setEnabled(enabled); - fSourceFileDialogField.setEnabled(enabled); - if (!enabled) { - updateFilesFromClassName(fClassNameDialogField.getText()); + if (field == fTestFileSelection) { + boolean enabled = fTestFileSelection.isSelected(); + fTestFileDialogField.setEnabled(enabled); + if (enabled) { + fTestFileDerivedFromClassName = true; + updateFilesFromClassName(fClassNameDialogField.getText().trim()); + } else { + fTestFileDialogField.setTextWithoutUpdate(""); //$NON-NLS-1$ } - changedFields = HEADER_FILE_ID | SOURCE_FILE_ID; - updateFileGroupEnableState(); + changedFields = TEST_FILE_ID; + updateTestFileEnableState(); handleFieldChanged(SOURCE_FOLDER_ID); } if (field == fHeaderFileDialogField) { changedFields |= HEADER_FILE_ID; + fHeaderFileDerivedFromClassName = false; } else if (field == fSourceFileDialogField) { changedFields |= SOURCE_FILE_ID; + fSourceFileDerivedFromClassName = false; + } else if (field == fTestFileDialogField) { + changedFields |= TEST_FILE_ID; + fTestFileDerivedFromClassName = false; } handleFieldChanged(changedFields); } } - private IPath chooseHeaderFile() { + private IPath chooseFile(String title, IPath initialPath) { SourceFileSelectionDialog dialog = new SourceFileSelectionDialog(getShell()); - dialog.setTitle(NewClassWizardMessages.NewClassCreationWizardPage_ChooseHeaderFileDialog_title); + dialog.setTitle(title); ICElement input = CoreModel.create(NewClassWizardUtil.getWorkspaceRoot()); ICProject project = getCurrentProject(); if (project != null) input = project; dialog.setInput(input); - IPath filePath = getHeaderFileFullPath(); + IPath filePath = initialPath; if (filePath != null) { String folderName = filePath.removeLastSegments(1).toString(); String fileName = filePath.lastSegment(); @@ -1244,52 +1339,32 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { return null; } - private IPath chooseSourceFile() { - SourceFileSelectionDialog dialog = new SourceFileSelectionDialog(getShell()); - dialog.setTitle(NewClassWizardMessages.NewClassCreationWizardPage_ChooseSourceFileDialog_title); - ICElement input = CoreModel.create(NewClassWizardUtil.getWorkspaceRoot()); - ICProject project = getCurrentProject(); - if (project != null) - input = project; - dialog.setInput(input); - - IPath filePath = getSourceFileFullPath(); - if (filePath != null) { - String folderName = filePath.removeLastSegments(1).toString(); - String fileName = filePath.lastSegment(); - dialog.setInitialSelection(folderName, fileName); - } else { - filePath = getSourceFolderFullPath(); - if (filePath != null) { - dialog.setInitialSelection(filePath.toString(), null); - } - } - - if (dialog.open() == Window.OK) { - return dialog.getFilePath(); - } - return null; - } - /** * update header and source file fields from the class name */ private void updateFilesFromClassName(String className) { - String headerName = null; - String sourceName = null; + String headerName = ""; //$NON-NLS-1$ + String sourceName = ""; //$NON-NLS-1$ + String testName = ""; //$NON-NLS-1$ IPath folder = getSourceFolderFullPath(); if (className != null && className.length() > 0) { String[] names = generateFileNames(className, folder); - if (names != null && names.length == 2) { + if (names != null && names.length == 3) { headerName = names[0]; sourceName = names[1]; + testName = names[2]; } } - fHeaderFileDialogField.setTextWithoutUpdate(headerName != null ? headerName : ""); //$NON-NLS-1$ - fSourceFileDialogField.setTextWithoutUpdate(sourceName != null ? sourceName : ""); //$NON-NLS-1$ + if (fHeaderFileDerivedFromClassName) + fHeaderFileDialogField.setTextWithoutUpdate(headerName); + if (fSourceFileDerivedFromClassName) + fSourceFileDialogField.setTextWithoutUpdate(sourceName); + if (fTestFileDerivedFromClassName && fTestFileDialogField.isEnabled()) + fTestFileDialogField.setTextWithoutUpdate(testName); } private static final int MAX_UNIQUE_CLASSNAME = 99; + private IDialogSettings fDialogSettings; /** * Returns the names of the header file and source file which will be @@ -1304,10 +1379,12 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { protected String[] generateFileNames(String className, IPath folder) { String headerName = null; String sourceName = null; + String testName = null; if (folder == null) { headerName = NewSourceFileGenerator.generateHeaderFileNameFromClass(className); sourceName = NewSourceFileGenerator.generateSourceFileNameFromClass(className); + testName = NewSourceFileGenerator.generateTestFileNameFromClass(className); } else { // make sure the file names are unique String currName = className; @@ -1322,10 +1399,15 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { String source = NewSourceFileGenerator.generateSourceFileNameFromClass(currName); path = folder.append(source); if (!path.toFile().exists()) { - headerName = header; - sourceName = source; - // we're done - break; + String test = NewSourceFileGenerator.generateTestFileNameFromClass(currName); + path = folder.append(test); + if (!path.toFile().exists()) { + headerName = header; + sourceName = source; + testName = test; + // we're done + break; + } } } ++count; @@ -1333,7 +1415,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { } } - return new String[] { headerName, sourceName }; + return new String[] { headerName, sourceName, testName }; } /** @@ -1366,6 +1448,9 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { if (fieldChanged(fields, SOURCE_FILE_ID)) { fSourceFileStatus = sourceFileChanged(); } + if (fieldChanged(fields, TEST_FILE_ID)) { + fTestFileStatus = testFileChanged(); + } doStatusUpdate(); } @@ -1389,16 +1474,17 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { (fSourceFolderStatus != lastStatus) ? fSourceFolderStatus : STATUS_OK, (fNamespaceStatus != lastStatus) ? fNamespaceStatus : STATUS_OK, - // give priority to file-level warnings over - // class name warnings + // Give priority to file-level warnings over class name warnings (fHeaderFileStatus != lastStatus && isClassNameWarning) ? fHeaderFileStatus : STATUS_OK, (fSourceFileStatus != lastStatus && isClassNameWarning) ? fSourceFileStatus : STATUS_OK, + (fTestFileStatus != lastStatus && isClassNameWarning) ? fTestFileStatus : STATUS_OK, (fClassNameStatus != lastStatus) ? fClassNameStatus : STATUS_OK, (fBaseClassesStatus != lastStatus) ? fBaseClassesStatus : STATUS_OK, (fMethodStubsStatus != lastStatus) ? fMethodStubsStatus : STATUS_OK, - (fSourceFileStatus != lastStatus) ? fSourceFileStatus : STATUS_OK, (fHeaderFileStatus != lastStatus) ? fHeaderFileStatus : STATUS_OK, + (fSourceFileStatus != lastStatus) ? fSourceFileStatus : STATUS_OK, + (fTestFileStatus != lastStatus) ? fTestFileStatus : STATUS_OK, }; // the mode severe status will be displayed and the ok button enabled/disabled. @@ -1412,22 +1498,24 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { */ protected IStatus getLastFocusedStatus() { switch (fLastFocusedField) { - case SOURCE_FOLDER_ID: - return fSourceFolderStatus; - case NAMESPACE_ID: - return fNamespaceStatus; - case CLASS_NAME_ID: - return fClassNameStatus; - case BASE_CLASSES_ID: - return fBaseClassesStatus; - case METHOD_STUBS_ID: - return fMethodStubsStatus; - case HEADER_FILE_ID: - return fHeaderFileStatus; - case SOURCE_FILE_ID: - return fSourceFileStatus; - default: - return STATUS_OK; + case SOURCE_FOLDER_ID: + return fSourceFolderStatus; + case NAMESPACE_ID: + return fNamespaceStatus; + case CLASS_NAME_ID: + return fClassNameStatus; + case BASE_CLASSES_ID: + return fBaseClassesStatus; + case METHOD_STUBS_ID: + return fMethodStubsStatus; + case HEADER_FILE_ID: + return fHeaderFileStatus; + case SOURCE_FILE_ID: + return fSourceFileStatus; + case TEST_FILE_ID: + return fTestFileStatus; + default: + return STATUS_OK; } } @@ -1463,10 +1551,8 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { status.setWarning(NewClassWizardMessages.NewClassCreationWizardPage_warning_NotInACProject); } if (NewClassWizardUtil.getSourceFolder(res) == null) { - if (isUseDefaultSelected()) { - status.setError(NLS.bind(NewClassWizardMessages.NewClassCreationWizardPage_error_NotASourceFolder, folderPath)); - return status; - } + status.setError(NLS.bind(NewClassWizardMessages.NewClassCreationWizardPage_error_NotASourceFolder, folderPath)); + return status; } } else { status.setError(NLS.bind(NewClassWizardMessages.NewClassCreationWizardPage_error_NotAFolder, folderPath)); @@ -1698,9 +1784,6 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { StatusInfo status = new StatusInfo(); IPath path = getHeaderFileFullPath(); - if (path == null && isUseDefaultSelected()) { - return status; - } if (path == null) { status.setError(NewClassWizardMessages.NewClassCreationWizardPage_error_EnterHeaderFileName); return status; @@ -1719,7 +1802,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { } boolean fileExists = false; - // check if file already exists + // Check if the file already exists IResource file = NewClassWizardUtil.getWorkspaceRoot().getFile(path); if (file.getType() == IResource.FILE) { if (!file.exists()) { @@ -1751,7 +1834,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { return status; } - // check if folder exists + // Check if folder exists IPath folderPath = path.removeLastSegments(1).makeRelative(); IResource folder = NewClassWizardUtil.getWorkspaceRoot().findMember(folderPath); if (folder == null || !folder.exists() || (folder.getType() != IResource.PROJECT && folder.getType() != IResource.FOLDER)) { @@ -1799,7 +1882,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { } boolean fileExists = false; - // check if file already exists + // Check if file already exists IResource file = NewClassWizardUtil.getWorkspaceRoot().getFile(path); if (file.getType() == IResource.FILE) { if (!file.exists()) { @@ -1831,7 +1914,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { return status; } - // check if folder exists + // Check if folder exists IPath folderPath = path.removeLastSegments(1).makeRelative(); IResource folder = NewClassWizardUtil.getWorkspaceRoot().findMember(folderPath); if (folder == null || !folder.exists() || (folder.getType() != IResource.PROJECT && folder.getType() != IResource.FOLDER)) { @@ -1851,6 +1934,90 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { return status; } + /** + * Hook method that gets called when the test file has changed. The method + * validates the test file and returns the status of the validation. + * + * @return the status of the validation + * @since 5.3 + */ + protected IStatus testFileChanged() { + StatusInfo status = new StatusInfo(); + + if (!fTestFileDialogField.isEnabled()) { + return status; + } + IPath path = getTestFileFullPath(); + if (path == null) { + status.setError(NewClassWizardMessages.NewClassCreationWizardPage_error_EnterTestFileName); + return status; + } + + IPath sourceFolderPath = getSourceFolderFullPath(); + if (sourceFolderPath == null || !sourceFolderPath.isPrefixOf(path)) { + status.setError(NewClassWizardMessages.NewClassCreationWizardPage_error_TestFileNotInSourceFolder); + return status; + } + + // Make sure the file location is under a source root + if (NewClassWizardUtil.getSourceFolder(path) == null) { + status.setError(NewClassWizardMessages.NewClassCreationWizardPage_error_TestFileNotInSourceFolder); + return status; + } + + boolean fileExists = false; + // Check if file already exists + IResource file = NewClassWizardUtil.getWorkspaceRoot().getFile(path); + if (file.getType() == IResource.FILE) { + if (!file.exists()) { + URI location = file.getLocationURI(); + try { + IFileStore store = EFS.getStore(location); + fileExists = store.fetchInfo().exists(); + } catch (CoreException e) { + status.setError(NewClassWizardMessages.NewClassCreationWizardPage_error_LocationUnknown); + return status; + } + } else { + fileExists = true; + } + + IProject proj = file.getProject(); + if (!proj.isOpen()) { + status.setError(NLS.bind(NewClassWizardMessages.NewClassCreationWizardPage_error_NotAFile, path)); + return status; + } + + if (!CoreModel.hasCCNature(proj) && !CoreModel.hasCNature(proj)) { + status.setWarning(NewClassWizardMessages.NewClassCreationWizardPage_warning_NotInACProject); + } else if (fileExists) { + status.setWarning(NewClassWizardMessages.NewClassCreationWizardPage_warning_TestFileExists); + } + } else { + status.setError(NewClassWizardMessages.NewClassCreationWizardPage_error_NotAFile); + return status; + } + + // Check if folder exists + IPath folderPath = path.removeLastSegments(1).makeRelative(); + IResource folder = NewClassWizardUtil.getWorkspaceRoot().findMember(folderPath); + if (folder == null || !folder.exists() || (folder.getType() != IResource.PROJECT && folder.getType() != IResource.FOLDER)) { + status.setError(NLS.bind(NewClassWizardMessages.NewClassCreationWizardPage_error_FolderDoesNotExist, folderPath)); + return status; + } + + if (!fileExists) { + IStatus val = CConventions.validateSourceFileName(getCurrentProject().getProject(), path.lastSegment()); + if (val.getSeverity() == IStatus.ERROR) { + status.setError(NLS.bind(NewClassWizardMessages.NewClassCreationWizardPage_error_InvalidTestFileName, val.getMessage())); + return status; + } else if (val.getSeverity() == IStatus.WARNING) { + status.setWarning(NLS.bind(NewClassWizardMessages.NewClassCreationWizardPage_warning_TestFileNameDiscouraged, val.getMessage())); + } + } + return status; + } + // -------- Code Generation --------- /** @@ -1861,15 +2028,37 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { * @throws InterruptedException Thrown when the operation was cancelled. */ public void createClass(IProgressMonitor monitor) throws CoreException, InterruptedException { - fCreatedClass = null; + // Update dialog settings. + fDialogSettings.put(KEY_NAMESPACE_SELECTED, fNamespaceSelection.isSelected()); + fDialogSettings.put(KEY_TEST_FILE_SELECTED, fTestFileSelection.isSelected()); + String namespace = fNamespaceSelection.isSelected() ? getNamespaceText() : null; + fDialogSettings.put(KEY_NAMESPACE, namespace); + IMethodStub[] stubs = fMethodStubsDialogField.getMethodStubs(); + for (int i = 0; i < stubs.length; ++i) { + IMethodStub stub = stubs[i]; + if (stub.canModifyVirtual()) { + fDialogSettings.put(KEY_STUB_VIRTUAL + i, stub.isVirtual()); + } + if (stub.canModifyInline()) { + fDialogSettings.put(KEY_STUB_INLINE + i, stub.isInline()); + } + fDialogSettings.put(KEY_STUB_SELECTED + i, fMethodStubsDialogField.isChecked(stub)); + } + + fCreatedClass = null; fCreatedHeaderFile = null; fCreatedSourceFile = null; - + fCreatedTestFile = null; + + IPath headerPath = getHeaderFileFullPath(); + IPath sourcePath = getSourceFileFullPath(); + IPath testPath = getTestFileFullPath(); createClass( - getCanonicalPath(getHeaderFileFullPath()), - getCanonicalPath(getSourceFileFullPath()), + headerPath != null ? getCanonicalPath(headerPath) : null, + sourcePath != null ? getCanonicalPath(sourcePath) : null, + testPath != null ? getCanonicalPath(testPath) : null, getClassName(), - isNamespaceSelected() ? getNamespaceText() : null, + namespace, getBaseClasses(), getSelectedMethodStubs(), monitor); } @@ -1902,6 +2091,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { * * @param headerPath the header file path * @param sourcePath the source file path + * @param testPath the test file path, can be {@code null}. * @param className the class name * @param namespace the namespace * @param baseClasses array of base classes @@ -1909,11 +2099,15 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { * @param monitor a progress monitor * @throws CoreException if the creation failed * @throws InterruptedException if the operation was cancelled + * @since 5.3 */ - protected void createClass(IPath headerPath, IPath sourcePath, String className, String namespace, IBaseClassInfo[] baseClasses, IMethodStub[] methodStubs, IProgressMonitor monitor) throws CoreException, InterruptedException { + protected void createClass(IPath headerPath, IPath sourcePath, IPath testPath, String className, + String namespace, IBaseClassInfo[] baseClasses, IMethodStub[] methodStubs, IProgressMonitor monitor) + throws CoreException, InterruptedException { NewClassCodeGenerator generator = new NewClassCodeGenerator( headerPath, sourcePath, + testPath, className, namespace, baseClasses, @@ -1924,8 +2118,16 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { fCreatedClass = generator.getCreatedClass(); fCreatedHeaderFile = generator.getCreatedHeaderFile(); fCreatedSourceFile = generator.getCreatedSourceFile(); + fCreatedTestFile = generator.getCreatedTestFile(); } + protected void createClass(IPath headerPath, IPath sourcePath, String className, String namespace, + IBaseClassInfo[] baseClasses, IMethodStub[] methodStubs, IProgressMonitor monitor) + throws CoreException, InterruptedException { + createClass(headerPath, sourcePath, null, className, namespace, baseClasses, methodStubs, + monitor); + } + /** * Returns the created class. The method only returns a valid class * after createClass has been called. @@ -1947,15 +2149,27 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { public IFile getCreatedHeaderFile() { return fCreatedHeaderFile; } - - /** - * Returns the created source file. The method only returns a valid file - * after createClass has been called. - * - * @return the created source file - * @see #createClass(IProgressMonitor) - */ + + /** + * Returns the created source file. The method only returns a valid file + * after createClass has been called. + * + * @return the created source file + * @see #createClass(IProgressMonitor) + */ public IFile getCreatedSourceFile() { - return fCreatedSourceFile; + return fCreatedSourceFile; + } + + /** + * Returns the created test file. The method only returns a valid file + * after createClass has been called. + * + * @return the created test file + * @see #createClass(IProgressMonitor) + * @since 5.3 + */ + public IFile getCreatedTestFile() { + return fCreatedTestFile; } } diff --git a/core/org.eclipse.cdt.ui/templates/default-codetemplates.xml b/core/org.eclipse.cdt.ui/templates/default-codetemplates.xml index 81325dc23d6..7efcef21724 100644 --- a/core/org.eclipse.cdt.ui/templates/default-codetemplates.xml +++ b/core/org.eclipse.cdt.ui/templates/default-codetemplates.xml @@ -11,6 +11,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Anton Leherbauer (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ --> @@ -45,21 +46,42 @@ +${includes} + +${namespace_begin} + +${declarations} + +${namespace_end} + + +${namespace_end} +#endif /* ${include_guard_symbol} */ #ifndef ${include_guard_symbol} #define ${include_guard_symbol} +${includes} + ${declarations} -#endif /* ${include_guard_symbol} */ - +#endif /* ${include_guard_symbol} */ - + - + - + + + + + + + diff --git a/core/org.eclipse.cdt.ui/templates/default-templates.properties b/core/org.eclipse.cdt.ui/templates/default-templates.properties index 20ba0e771cb..e4688b72a92 100644 --- a/core/org.eclipse.cdt.ui/templates/default-templates.properties +++ b/core/org.eclipse.cdt.ui/templates/default-templates.properties @@ -7,6 +7,7 @@ # # Contributors: # IBM Corporation - initial API and implementation +# Sergey Prigogin (Google) ############################################################################### ## NOTE TO TRANSLATORS: @@ -46,13 +47,18 @@ CodeTemplates.methodcomment=Comment for methods CodeTemplates.cppsourcefile=Default C++ source template CodeTemplates.cppheaderfile=Default C++ header template +CodeTemplates.cpptestfile=Default C++ test template CodeTemplates.csourcefile=Default C source template CodeTemplates.cheaderfile=Default C header template CodeTemplates.cppsourcefile.desc=Default template for newly created C++ source files CodeTemplates.cppheaderfile.desc=Default template for newly created C++ header files +CodeTemplates.cpptestfile.desc=Default template for newly created C++ test files CodeTemplates.csourcefile.desc=Default template for newly created C source files CodeTemplates.cheaderfile.desc=Default template for newly created C header files +CodeTemplates.namespace_begin=Beginning of namespace declaration +CodeTemplates.namespace_end=End of namespace declaration +CodeTemplates.class_body=Code in created class definitions CodeTemplates.methodstub=Code in created method stubs CodeTemplates.constructorstub=Code in created constructor stubs CodeTemplates.destructorstub=Code in created destructor stubs