blob: 0c9950ab62a35ed6a3985d51cc9ac670be752b5e [file] [log] [blame]
#!/usr/bin/env python3
#
# Copyright 2018 - The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Config class."""
import copy
import json
import logging
import os
import re
from aidegen.lib import common_util
class AidegenConfig():
"""Class manages AIDEGen's configurations.
Attributes:
_config: A dict contains the aidegen config.
_config_backup: A dict contains the aidegen config.
"""
# Constants of AIDEGen config
_DEFAULT_CONFIG_FILE = 'aidegen.config'
_CONFIG_DIR = os.path.join(
os.path.expanduser('~'), '.config', 'asuite', 'aidegen')
_CONFIG_FILE_PATH = os.path.join(_CONFIG_DIR, _DEFAULT_CONFIG_FILE)
# Constants of enable debugger
_ENABLE_DEBUG_CONFIG_DIR = 'enable_debugger'
_ENABLE_DEBUG_CONFIG_FILE = 'enable_debugger.iml'
_ENABLE_DEBUG_TEMPLATE_FILE = os.path.join(
common_util.get_aidegen_root_dir(), 'templates',
_ENABLE_DEBUG_CONFIG_DIR, _ENABLE_DEBUG_CONFIG_FILE)
_ENABLE_DEBUG_DIR = os.path.join(_CONFIG_DIR, _ENABLE_DEBUG_CONFIG_DIR)
_ANDROID_MANIFEST_FILE_NAME = 'AndroidManifest.xml'
_DIR_SRC = 'src'
_DIR_GEN = 'gen'
_ANDROIDMANIFEST_CONTENT = """<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0" >
</manifest>
"""
DEBUG_ENABLED_FILE_PATH = os.path.join(_ENABLE_DEBUG_DIR,
_ENABLE_DEBUG_CONFIG_FILE)
def __init__(self):
self._config = {}
self._config_backup = {}
self._create_config_folder()
def __enter__(self):
self._load_aidegen_config()
self._config_backup = copy.deepcopy(self._config)
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self._save_aidegen_config()
@property
def preferred_version(self):
"""AIDEGen configuration getter.
Returns:
The preferred verson item of configuration data if exists, otherwise
None.
"""
return self._config.get('preferred_version', '')
@preferred_version.setter
def preferred_version(self, preferred_version):
"""AIDEGen configuration setter.
Args:
preferred_version: A string, user's preferred version to be set.
"""
self._config['preferred_version'] = preferred_version
def _load_aidegen_config(self):
"""Load data from configuration file."""
if os.path.exists(self._CONFIG_FILE_PATH):
try:
with open(self._CONFIG_FILE_PATH, 'r') as cfg_file:
self._config = json.load(cfg_file)
except ValueError as err:
info = '{} format is incorrect, error: {}'.format(
self._CONFIG_FILE_PATH, err)
logging.info(info)
except IOError as err:
logging.error(err)
raise
def _save_aidegen_config(self):
"""Save data to configuration file."""
if self._is_config_modified():
with open(self._CONFIG_FILE_PATH, 'w') as cfg_file:
json.dump(self._config, cfg_file, indent=4)
def _is_config_modified(self):
"""Check if configuration data is modified."""
return any(key for key in self._config if not key in self._config_backup
or self._config[key] != self._config_backup[key])
def _create_config_folder(self):
"""Create the config folder if it doesn't exist."""
if not os.path.exists(self._CONFIG_DIR):
os.makedirs(self._CONFIG_DIR)
def _gen_enable_debug_sub_dir(self, dir_name):
"""Generate a dir under enable debug dir.
Args:
dir_name: A string of the folder name.
"""
_dir = os.path.join(self._ENABLE_DEBUG_DIR, dir_name)
if not os.path.exists(_dir):
os.makedirs(_dir)
def _gen_empty_androidmanifest(self):
"""Generate an empty AndroidManifest.xml under enable debug dir.
Once the AndroidManifest.xml does not exist or file size is zero,
AIDEGen will generate it with default content to prevent the red
underline error in IntelliJ.
"""
_file = os.path.join(self._ENABLE_DEBUG_DIR,
self._ANDROID_MANIFEST_FILE_NAME)
if not os.path.exists(_file) or os.stat(_file).st_size == 0:
common_util.file_generate(_file, self._ANDROIDMANIFEST_CONTENT)
def _gen_enable_debugger_config(self, api_level):
"""Generate the enable_debugger.iml config file.
Create the enable_debugger.iml if it doesn't exist.
Args:
api_level: An integer of API level.
"""
if not os.path.exists(self.DEBUG_ENABLED_FILE_PATH):
content = common_util.read_file_content(
self._ENABLE_DEBUG_TEMPLATE_FILE).format(API_LEVEL=api_level)
common_util.file_generate(self.DEBUG_ENABLED_FILE_PATH, content)
def create_enable_debugger_module(self, api_level):
"""Create the enable_debugger module.
1. Create two empty folders named src and gen.
2. Create an empty file named AndroidManifest.xml
3. Create the enable_denugger.iml.
Args:
api_level: An integer of API level.
Returns: True if successfully generate the enable debugger module,
otherwise False.
"""
try:
self._gen_enable_debug_sub_dir(self._DIR_SRC)
self._gen_enable_debug_sub_dir(self._DIR_GEN)
self._gen_empty_androidmanifest()
self._gen_enable_debugger_config(api_level)
return True
except (IOError, OSError) as err:
logging.warning(('Can\'t create the enable_debugger module in %s.\n'
'%s'), self._CONFIG_DIR, err)
return False
class IdeaProperties():
"""Class manages IntelliJ's idea.properties attribute.
Class Attributes:
_PROPERTIES_FILE: The property file name of IntelliJ.
_KEY_FILESIZE: The key name of the maximun file size.
_FILESIZE_LIMIT: The value to be set as the max file size.
_RE_SEARCH_FILESIZE: A regular expression to find the current max file
size.
_PROPERTIES_CONTENT: The default content of idea.properties to be
generated.
Attributes:
idea_file: The absolute path of the idea.properties.
For example:
In Linux, it is ~/.IdeaIC2019.1/config/idea.properties.
In Mac, it is ~/Library/Preferences/IdeaIC2019.1/
idea.properties.
"""
# Constants of idea.properties
_PROPERTIES_FILE = 'idea.properties'
_KEY_FILESIZE = 'idea.max.intellisense.filesize'
_FILESIZE_LIMIT = 100000
_RE_SEARCH_FILESIZE = r'%s\s?=\s?(?P<value>\d+)' % _KEY_FILESIZE
_PROPERTIES_CONTENT = """# custom IntelliJ IDEA properties
#-------------------------------------------------------------------------------
# Maximum size of files (in kilobytes) for which IntelliJ IDEA provides coding
# assistance. Coding assistance for large files can affect editor performance
# and increase memory consumption.
# The default value is 2500.
#-------------------------------------------------------------------------------
idea.max.intellisense.filesize=100000
"""
def __init__(self, config_dir):
"""IdeaProperties initialize.
Args:
config_dir: The absolute dir of the idea.properties.
"""
self.idea_file = os.path.join(config_dir, self._PROPERTIES_FILE)
def _set_default_idea_properties(self):
"""Create the file idea.properties."""
common_util.file_generate(self.idea_file, self._PROPERTIES_CONTENT)
def _reset_max_file_size(self):
"""Reset the max file size value in the idea.properties."""
updated_flag = False
properties = common_util.read_file_content(self.idea_file).splitlines()
for index, line in enumerate(properties):
res = re.search(self._RE_SEARCH_FILESIZE, line)
if res and int(res['value']) < self._FILESIZE_LIMIT:
updated_flag = True
properties[index] = '%s=%s' % (self._KEY_FILESIZE,
str(self._FILESIZE_LIMIT))
if updated_flag:
common_util.file_generate(self.idea_file, '\n'.join(properties))
def set_max_file_size(self):
"""Set the max file size parameter in the idea.properties."""
if not os.path.exists(self.idea_file):
self._set_default_idea_properties()
else:
self._reset_max_file_size()