templates: use a common template for C# and Java

The only real differences between these generators is the file extension
and the templates themselves. We can uses a shared abstract class
with a few abstract properties to provide all of this to the same base
class. This results in less code duplication and easier maintanence.

I've made a few cleanups to the shared template:
- use `str.capitalize()` instead of `str.upper()[0] + str[1:]`
- use `open` as a context manager
- use f-strings
- put some duplicate calculations in the initializer
pull/12044/head
Dylan Baker 2 years ago committed by Eli Schwartz
parent bbe649a5fc
commit 5449d10f01
  1. 51
      mesonbuild/templates/cstemplates.py
  2. 49
      mesonbuild/templates/javatemplates.py
  3. 31
      mesonbuild/templates/samplefactory.py
  4. 78
      mesonbuild/templates/sampleimpl.py

@ -13,9 +13,7 @@
# limitations under the License.
from __future__ import annotations
import re
from mesonbuild.templates.sampleimpl import SampleImpl
from mesonbuild.templates.sampleimpl import ClassImpl
hello_cs_template = '''using System;
@ -92,42 +90,11 @@ test('{test_name}', test_exe)
'''
class CSharpProject(SampleImpl):
def create_executable(self) -> None:
lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
uppercase_token = lowercase_token.upper()
class_name = uppercase_token[0] + lowercase_token[1:]
source_name = uppercase_token[0] + lowercase_token[1:] + '.cs'
open(source_name, 'w', encoding='utf-8').write(
hello_cs_template.format(project_name=self.name,
class_name=class_name))
open('meson.build', 'w', encoding='utf-8').write(
hello_cs_meson_template.format(project_name=self.name,
exe_name=self.name,
source_name=source_name,
version=self.version))
def create_library(self) -> None:
lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
uppercase_token = lowercase_token.upper()
class_name = uppercase_token[0] + lowercase_token[1:]
class_test = uppercase_token[0] + lowercase_token[1:] + '_test'
project_test = lowercase_token + '_test'
lib_cs_name = uppercase_token[0] + lowercase_token[1:] + '.cs'
test_cs_name = uppercase_token[0] + lowercase_token[1:] + '_test.cs'
kwargs = {'utoken': uppercase_token,
'ltoken': lowercase_token,
'class_test': class_test,
'class_name': class_name,
'source_file': lib_cs_name,
'test_source_file': test_cs_name,
'test_exe_name': project_test,
'project_name': self.name,
'lib_name': lowercase_token,
'test_name': lowercase_token,
'version': self.version,
}
open(lib_cs_name, 'w', encoding='utf-8').write(lib_cs_template.format(**kwargs))
open(test_cs_name, 'w', encoding='utf-8').write(lib_cs_test_template.format(**kwargs))
open('meson.build', 'w', encoding='utf-8').write(lib_cs_meson_template.format(**kwargs))
class CSharpProject(ClassImpl):
source_ext = 'cs'
exe_template = hello_cs_template
exe_meson_template = hello_cs_meson_template
lib_template = lib_cs_template
lib_test_template = lib_cs_test_template
lib_meson_template = lib_cs_meson_template

@ -13,9 +13,7 @@
# limitations under the License.
from __future__ import annotations
import re
from mesonbuild.templates.sampleimpl import SampleImpl
from mesonbuild.templates.sampleimpl import ClassImpl
hello_java_template = '''
@ -96,40 +94,11 @@ test('{test_name}', test_jar)
'''
class JavaProject(SampleImpl):
def create_executable(self) -> None:
lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
uppercase_token = lowercase_token.upper()
class_name = uppercase_token[0] + lowercase_token[1:]
source_name = uppercase_token[0] + lowercase_token[1:] + '.java'
open(source_name, 'w', encoding='utf-8').write(
hello_java_template.format(project_name=self.name,
class_name=class_name))
open('meson.build', 'w', encoding='utf-8').write(
hello_java_meson_template.format(project_name=self.name,
exe_name=class_name,
source_name=source_name,
version=self.version))
def create_library(self) -> None:
lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
uppercase_token = lowercase_token.upper()
class_name = uppercase_token[0] + lowercase_token[1:]
class_test = uppercase_token[0] + lowercase_token[1:] + '_test'
lib_java_name = uppercase_token[0] + lowercase_token[1:] + '.java'
test_java_name = uppercase_token[0] + lowercase_token[1:] + '_test.java'
kwargs = {'utoken': uppercase_token,
'ltoken': lowercase_token,
'class_test': class_test,
'class_name': class_name,
'source_file': lib_java_name,
'test_source_file': test_java_name,
'project_name': self.name,
'lib_name': lowercase_token,
'test_name': lowercase_token,
'version': self.version,
}
open(lib_java_name, 'w', encoding='utf-8').write(lib_java_template.format(**kwargs))
open(test_java_name, 'w', encoding='utf-8').write(lib_java_test_template.format(**kwargs))
open('meson.build', 'w', encoding='utf-8').write(lib_java_meson_template.format(**kwargs))
class JavaProject(ClassImpl):
source_ext = 'java'
exe_template = hello_java_template
exe_meson_template = hello_java_meson_template
lib_template = lib_java_template
lib_test_template = lib_java_test_template
lib_meson_template = lib_java_meson_template

@ -29,20 +29,23 @@ from mesonbuild.templates.ctemplates import CProject
if T.TYPE_CHECKING:
from ..minit import Arguments
from .sampleimpl import SampleImpl
from .sampleimpl import ClassImpl, SampleImpl
_IMPL: T.Mapping[str, T.Union[T.Type[ClassImpl], T.Type[SampleImpl]]] = {
'c': CProject,
'cpp': CppProject,
'cs': CSharpProject,
'cuda': CudaProject,
'objc': ObjCProject,
'objcpp': ObjCppProject,
'java': JavaProject,
'd': DlangProject,
'rust': RustProject,
'fortran': FortranProject,
'vala': ValaProject,
}
def sample_generator(options: Arguments) -> SampleImpl:
return {
'c': CProject,
'cpp': CppProject,
'cs': CSharpProject,
'cuda': CudaProject,
'objc': ObjCProject,
'objcpp': ObjCppProject,
'java': JavaProject,
'd': DlangProject,
'rust': RustProject,
'fortran': FortranProject,
'vala': ValaProject
}[options.language](options)
return _IMPL[options.language](options)

@ -13,20 +13,92 @@
# limitations under the License.
from __future__ import annotations
import abc
import re
import typing as T
if T.TYPE_CHECKING:
from ..minit import Arguments
class SampleImpl:
class SampleImpl(metaclass=abc.ABCMeta):
def __init__(self, args: Arguments):
self.name = args.name
self.version = args.version
@abc.abstractmethod
def create_executable(self) -> None:
raise NotImplementedError('Sample implementation for "executable" not implemented!')
pass
@abc.abstractmethod
def create_library(self) -> None:
raise NotImplementedError('Sample implementation for "library" not implemented!')
pass
class ClassImpl(SampleImpl):
"""For Class based languages, like Java and C#"""
def __init__(self, args: Arguments):
super().__init__(args)
self.lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
self.uppercase_token = self.lowercase_token.upper()
self.capitalized_token = self.lowercase_token.capitalize()
@abc.abstractproperty
def exe_template(self) -> str:
pass
@abc.abstractproperty
def exe_meson_template(self) -> str:
pass
@abc.abstractproperty
def lib_template(self) -> str:
pass
@abc.abstractproperty
def lib_test_template(self) -> str:
pass
@abc.abstractproperty
def lib_meson_template(self) -> str:
pass
@abc.abstractproperty
def source_ext(self) -> str:
pass
def create_executable(self) -> None:
source_name = f'{self.capitalized_token}.{self.source_ext}'
with open(source_name, 'w', encoding='utf-8') as f:
f.write(self.exe_template.format(project_name=self.name,
class_name=self.capitalized_token))
with open('meson.build', 'w', encoding='utf-8') as f:
f.write(self.exe_meson_template.format(project_name=self.name,
exe_name=self.name,
source_name=source_name,
version=self.version))
def create_library(self) -> None:
lib_name = f'{self.capitalized_token}.{self.source_ext}'
test_name = f'{self.capitalized_token}_test.{self.source_ext}'
kwargs = {'utoken': self.uppercase_token,
'ltoken': self.lowercase_token,
'class_test': f'{self.capitalized_token}_test',
'class_name': self.capitalized_token,
'source_file': lib_name,
'test_source_file': test_name,
'test_exe_name': f'{self.lowercase_token}_test',
'project_name': self.name,
'lib_name': self.lowercase_token,
'test_name': self.lowercase_token,
'version': self.version,
}
with open(lib_name, 'w', encoding='utf-8') as f:
f.write(self.lib_template.format(**kwargs))
with open(test_name, 'w', encoding='utf-8') as f:
f.write(self.lib_test_template.format(**kwargs))
with open('meson.build', 'w', encoding='utf-8') as f:
f.write(self.lib_meson_template.format(**kwargs))

Loading…
Cancel
Save