Merge pull request #301 from TouchInstinct/release/vuzbank_c2b
release/vuzbank_c2b -> vuzbank
This commit is contained in:
commit
e4465fc6d1
|
|
@ -0,0 +1,3 @@
|
|||
# macOS
|
||||
|
||||
.DS_Store
|
||||
|
|
@ -1,210 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module PUBLIC
|
||||
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
|
||||
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
|
||||
|
||||
<!--
|
||||
|
||||
Checkstyle configuration that checks the Google coding conventions from:
|
||||
|
||||
- Google Java Style
|
||||
https://google-styleguide.googlecode.com/svn-history/r130/trunk/javaguide.html
|
||||
|
||||
Checkstyle is very configurable. Be sure to read the documentation at
|
||||
http://checkstyle.sf.net (or in your downloaded distribution).
|
||||
|
||||
Most Checks are configurable, be sure to consult the documentation.
|
||||
|
||||
To completely disable a check, just comment it out or delete it from the file.
|
||||
|
||||
Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
|
||||
|
||||
-->
|
||||
|
||||
<module name = "Checker">
|
||||
<property name="charset" value="UTF-8"/>
|
||||
|
||||
<property name="severity" value="warning"/>
|
||||
|
||||
<property name="fileExtensions" value="java, properties, xml"/>
|
||||
<!-- Checks for whitespace -->
|
||||
<!-- See http://checkstyle.sf.net/config_whitespace.html -->
|
||||
<module name="FileTabCharacter">
|
||||
<property name="eachLine" value="true"/>
|
||||
</module>
|
||||
|
||||
<module name="TreeWalker">
|
||||
<module name="MethodLength">
|
||||
<property name="max" value="40"/>
|
||||
</module>
|
||||
<module name="FinalParameters">
|
||||
<property name="tokens" value="METHOD_DEF, CTOR_DEF, LITERAL_CATCH, FOR_EACH_CLAUSE"/>
|
||||
</module>
|
||||
|
||||
<module name="OuterTypeFilename"/>
|
||||
<module name="IllegalTokenText">
|
||||
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
|
||||
<property name="format" value="\\u00(08|09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
|
||||
<property name="message" value="Avoid using corresponding octal or Unicode escape."/>
|
||||
</module>
|
||||
<module name="AvoidEscapedUnicodeCharacters">
|
||||
<property name="allowEscapesForControlCharacters" value="true"/>
|
||||
<property name="allowByTailComment" value="true"/>
|
||||
<property name="allowNonPrintableEscapes" value="true"/>
|
||||
</module>
|
||||
<module name="LineLength">
|
||||
<property name="max" value="150"/>
|
||||
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
|
||||
</module>
|
||||
<module name="AvoidStarImport"/>
|
||||
<module name="OneTopLevelClass"/>
|
||||
<module name="NoLineWrap"/>
|
||||
<module name="EmptyBlock">
|
||||
<property name="option" value="TEXT"/>
|
||||
<property name="tokens" value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
|
||||
</module>
|
||||
<module name="NeedBraces"/>
|
||||
<module name="LeftCurly">
|
||||
<property name="maxLineLength" value="150"/>
|
||||
</module>
|
||||
<module name="RightCurly"/>
|
||||
<module name="RightCurly">
|
||||
<property name="option" value="alone"/>
|
||||
<property name="tokens" value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, LITERAL_DO, STATIC_INIT, INSTANCE_INIT"/>
|
||||
</module>
|
||||
<module name="WhitespaceAround">
|
||||
<property name="allowEmptyConstructors" value="true"/>
|
||||
<property name="allowEmptyMethods" value="true"/>
|
||||
<property name="allowEmptyTypes" value="true"/>
|
||||
<property name="allowEmptyLoops" value="true"/>
|
||||
<message key="ws.notFollowed"
|
||||
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
|
||||
<message key="ws.notPreceded"
|
||||
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
|
||||
</module>
|
||||
<module name="OneStatementPerLine"/>
|
||||
<module name="MultipleVariableDeclarations"/>
|
||||
<module name="ArrayTypeStyle"/>
|
||||
<module name="MissingSwitchDefault"/>
|
||||
<module name="FallThrough"/>
|
||||
<module name="UpperEll"/>
|
||||
<module name="ModifierOrder"/>
|
||||
<module name="EmptyLineSeparator">
|
||||
<property name="allowNoEmptyLineBetweenFields" value="true"/>
|
||||
</module>
|
||||
<module name="SeparatorWrap">
|
||||
<property name="tokens" value="DOT"/>
|
||||
<property name="option" value="nl"/>
|
||||
</module>
|
||||
<module name="SeparatorWrap">
|
||||
<property name="tokens" value="COMMA"/>
|
||||
<property name="option" value="EOL"/>
|
||||
</module>
|
||||
<module name="PackageName">
|
||||
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Package name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="TypeName">
|
||||
<message key="name.invalidPattern"
|
||||
value="Type name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="MemberName">
|
||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Member name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="ParameterName">
|
||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="LocalVariableName">
|
||||
<property name="tokens" value="VARIABLE_DEF"/>
|
||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
|
||||
<property name="allowOneCharVarInForLoop" value="true"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="ClassTypeParameterName">
|
||||
<property name="format" value="^[T]([A-Z][a-zA-Z0-9]*)?$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Class type name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="MethodTypeParameterName">
|
||||
<property name="format" value="^[T]([A-Z][a-zA-Z0-9]*)?$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Method type name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="NoFinalizer"/>
|
||||
<module name="GenericWhitespace">
|
||||
<message key="ws.followed"
|
||||
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
|
||||
<message key="ws.preceded"
|
||||
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
|
||||
<message key="ws.illegalFollow"
|
||||
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
|
||||
<message key="ws.notPreceded"
|
||||
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
|
||||
</module>
|
||||
<module name="Indentation">
|
||||
<property name="basicOffset" value="4"/>
|
||||
<property name="braceAdjustment" value="0"/>
|
||||
<property name="caseIndent" value="4"/>
|
||||
<property name="throwsIndent" value="4"/>
|
||||
<property name="lineWrappingIndentation" value="4"/>
|
||||
<property name="arrayInitIndent" value="4"/>
|
||||
</module>
|
||||
<module name="AbbreviationAsWordInName">
|
||||
<property name="ignoreFinal" value="false"/>
|
||||
<property name="allowedAbbreviationLength" value="1"/>
|
||||
</module>
|
||||
<module name="OverloadMethodsDeclarationOrder"/>
|
||||
<module name="VariableDeclarationUsageDistance"/>
|
||||
<module name="MethodParamPad"/>
|
||||
<module name="OperatorWrap">
|
||||
<property name="option" value="NL"/>
|
||||
<property name="tokens" value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR "/>
|
||||
</module>
|
||||
<module name="AnnotationLocation">
|
||||
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
|
||||
</module>
|
||||
<module name="AnnotationLocation">
|
||||
<property name="tokens" value="VARIABLE_DEF"/>
|
||||
<property name="allowSamelineMultipleAnnotations" value="true"/>
|
||||
</module>
|
||||
<module name="NonEmptyAtclauseDescription"/>
|
||||
<module name="JavadocTagContinuationIndentation"/>
|
||||
<module name="SummaryJavadocCheck">
|
||||
<property name="forbiddenSummaryFragments" value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
|
||||
</module>
|
||||
<module name="JavadocParagraph"/>
|
||||
<module name="AtclauseOrder">
|
||||
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
|
||||
<property name="target" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
|
||||
</module>
|
||||
<module name="JavadocMethod">
|
||||
<property name="scope" value="nothing"/>
|
||||
<property name="allowMissingParamTags" value="true"/>
|
||||
<property name="allowMissingThrowsTags" value="true"/>
|
||||
<property name="allowMissingReturnTag" value="true"/>
|
||||
<property name="minLineCount" value="2"/>
|
||||
<property name="allowedAnnotations" value="Override, Test"/>
|
||||
<property name="allowThrowsTagsForSubclasses" value="true"/>
|
||||
</module>
|
||||
<module name="MethodName">
|
||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Method name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="SingleLineJavadoc"/>
|
||||
<module name="EmptyCatchBlock">
|
||||
<property name="exceptionVariableName" value="expected"/>
|
||||
</module>
|
||||
<module name="SuppressWarningsHolder" />
|
||||
</module>
|
||||
<module name="SuppressWarningsFilter" />
|
||||
|
||||
|
||||
|
||||
</module>
|
||||
|
|
@ -1,339 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module PUBLIC
|
||||
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
|
||||
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
|
||||
|
||||
<module name="Checker">
|
||||
<property name="charset" value="UTF-8"/>
|
||||
<property name="severity" value="warning"/>
|
||||
<property name="fileExtensions" value="java, properties, xml"/>
|
||||
|
||||
<module name="FileTabCharacter">
|
||||
<property name="eachLine" value="true"/>
|
||||
</module>
|
||||
|
||||
<module name="TreeWalker">
|
||||
<!-- CUSTOM CHECKS START-->
|
||||
<module name="NullAnnotationsCheck"/>
|
||||
<module name="CustomDeclarationOrder">
|
||||
<property name="customDeclarationOrder"
|
||||
value="Field(static final)
|
||||
### Field(static)
|
||||
### Ctor(static)
|
||||
### Method(static)
|
||||
### Field(.*)
|
||||
### Ctor(.*)
|
||||
### Method(.*)
|
||||
### InnerEnum(.*)
|
||||
### InnerInterface(.*)
|
||||
### InnerClass(.*)"/>
|
||||
</module>
|
||||
<!-- CUSTOM CHECKS END-->
|
||||
|
||||
<module name="AbbreviationAsWordInName">
|
||||
<property name="ignoreFinal" value="false"/>
|
||||
<property name="allowedAbbreviationLength" value="1"/>
|
||||
</module>
|
||||
<!-- <module name="AbstractClassName"/> -->
|
||||
<module name="AnnotationLocation">
|
||||
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
|
||||
<property name="allowSamelineSingleParameterlessAnnotation" value="false"/>
|
||||
</module>
|
||||
<module name="AnnotationLocation">
|
||||
<property name="tokens"
|
||||
value="VARIABLE_DEF, PARAMETER_DEF, ANNOTATION_DEF, TYPECAST, LITERAL_THROWS, IMPLEMENTS_CLAUSE, TYPE_ARGUMENT, LITERAL_NEW, DOT, ANNOTATION_FIELD_DEF"/>
|
||||
<property name="allowSamelineMultipleAnnotations" value="true"/>
|
||||
</module>
|
||||
<!-- <module name="AnnotationUseStyle"/> -->
|
||||
<!-- <module name="AnonInnerLength"/> -->
|
||||
<!-- <module name="ArrayTrailingComma"/> -->
|
||||
<module name="ArrayTypeStyle"/>
|
||||
<module name="AtclauseOrder">
|
||||
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
|
||||
<property name="target" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
|
||||
</module>
|
||||
<module name="AvoidEscapedUnicodeCharacters">
|
||||
<property name="allowEscapesForControlCharacters" value="true"/>
|
||||
<property name="allowByTailComment" value="true"/>
|
||||
<property name="allowNonPrintableEscapes" value="true"/>
|
||||
</module>
|
||||
<!-- <module name="AvoidInlineConditionals"/> -->
|
||||
<module name="AvoidNestedBlocks">
|
||||
<property name="allowInSwitchCase" value="true"/>
|
||||
</module>
|
||||
<module name="AvoidStarImport"/>
|
||||
<module name="AvoidStaticImport"/>
|
||||
<!-- <module name="BooleanExpressionComplexity"/> -->
|
||||
<module name="CatchParameterName">
|
||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<!-- <module name="ClassDataAbstractionCoupling"/> -->
|
||||
<!-- <module name="ClassFanOutComplexity"/> -->
|
||||
<module name="ClassTypeParameterName">
|
||||
<property name="format" value="^[T]([A-Z][a-zA-Z0-9]*)?$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Class type name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="CommentsIndentation"/>
|
||||
<module name="ConstantName"/>
|
||||
<!-- <module name="CovariantEquals"/> -->
|
||||
<!-- <module name="CustomImportOrder"/> -->
|
||||
<!-- <module name="CyclomaticComplexity"/> -->
|
||||
<!-- <module name="DeclarationOrder"/> -->
|
||||
<module name="DefaultComesLast"/>
|
||||
<!-- <module name="DescendantToken"/> -->
|
||||
<!-- <module name="DesignForExtension"/> -->
|
||||
<module name="EmptyBlock">
|
||||
<property name="option" value="TEXT"/>
|
||||
<property name="tokens"
|
||||
value="LITERAL_WHILE, LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_DO, LITERAL_IF, LITERAL_ELSE, LITERAL_FOR, INSTANCE_INIT, STATIC_INIT, LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_CASE, LITERAL_DEFAULT"/>
|
||||
</module>
|
||||
<module name="EmptyCatchBlock">
|
||||
<property name="exceptionVariableName" value="expected"/>
|
||||
</module>
|
||||
<!-- <module name="EmptyForInitializerPad"/> -->
|
||||
<!-- <module name="EmptyForIteratorPad"/> -->
|
||||
<module name="EmptyLineSeparator">
|
||||
<property name="allowNoEmptyLineBetweenFields" value="true"/>
|
||||
</module>
|
||||
<module name="EmptyStatement"/>
|
||||
<!-- <module name="EqualsAvoidNull"/> -->
|
||||
<module name="EqualsHashCode"/>
|
||||
<!-- <module name="ExecutableStatementCount"/> -->
|
||||
<!-- <module name="ExplicitInitialization"/> -->
|
||||
<module name="FallThrough"/>
|
||||
<!-- <module name="FileLength"/> -->
|
||||
<!-- <module name="FinalClass"/> -->
|
||||
<module name="FinalLocalVariable"/>
|
||||
<module name="FinalParameters">
|
||||
<property name="tokens" value="METHOD_DEF, CTOR_DEF, LITERAL_CATCH, FOR_EACH_CLAUSE"/>
|
||||
</module>
|
||||
<module name="GenericWhitespace">
|
||||
<message key="ws.followed"
|
||||
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
|
||||
<message key="ws.preceded"
|
||||
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
|
||||
<message key="ws.illegalFollow"
|
||||
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
|
||||
<message key="ws.notPreceded"
|
||||
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
|
||||
</module>
|
||||
<!-- <module name="Header"/> -->
|
||||
<!-- <module name="HiddenField"> -->
|
||||
<!-- <module name="HideUtilityClassConstructor"/> -->
|
||||
<!-- <module name="IllegalCatch"/> -->
|
||||
<!-- <module name="IllegalImport"/> -->
|
||||
<!-- <module name="IllegalInstantiation"/> -->
|
||||
<!-- <module name="IllegalThrows"/> -->
|
||||
<!-- <module name="IllegalToken"/> -->
|
||||
<module name="IllegalTokenText">
|
||||
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
|
||||
<property name="format" value="\\u00(08|09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
|
||||
<property name="message" value="Avoid using corresponding octal or Unicode escape."/>
|
||||
</module>
|
||||
<!-- <module name="IllegalType"/> -->
|
||||
<!-- <module name="ImportControl"/> -->
|
||||
<!-- <module name="ImportOrder"/> -->
|
||||
<module name="Indentation">
|
||||
<property name="basicOffset" value="4"/>
|
||||
<property name="braceAdjustment" value="0"/>
|
||||
<property name="caseIndent" value="4"/>
|
||||
<property name="throwsIndent" value="4"/>
|
||||
<property name="lineWrappingIndentation" value="4"/>
|
||||
<property name="arrayInitIndent" value="8"/>
|
||||
</module>
|
||||
<module name="InnerAssignment"/>
|
||||
<module name="InnerTypeLast"/>
|
||||
<module name="InterfaceIsType"/>
|
||||
<module name="InterfaceTypeParameterName">
|
||||
<property name="format" value="^[T]([A-Z][a-zA-Z0-9]*)?$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Class type name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="JavadocMethod">
|
||||
<property name="scope" value="nothing"/>
|
||||
<property name="allowMissingParamTags" value="true"/>
|
||||
<property name="allowMissingThrowsTags" value="true"/>
|
||||
<property name="allowMissingReturnTag" value="true"/>
|
||||
<property name="minLineCount" value="2"/>
|
||||
<property name="allowedAnnotations" value="Override, Test"/>
|
||||
<property name="allowThrowsTagsForSubclasses" value="true"/>
|
||||
</module>
|
||||
<!-- <module name="JavadocPackage"/> -->
|
||||
<module name="JavadocParagraph"/>
|
||||
<!-- <module name="JavadocStyle"/> -->
|
||||
<!-- https://youtrack.jetbrains.com/issue/IDEA-121723 <module name="JavadocTagContinuationIndentation"/> -->
|
||||
<!-- <module name="JavadocType"/> -->
|
||||
<!-- <module name="JavadocVariable"/> -->
|
||||
<!-- <module name="JavaNCSS"/> -->
|
||||
<module name="LeftCurly">
|
||||
<property name="maxLineLength" value="150"/>
|
||||
</module>
|
||||
<module name="LineLength">
|
||||
<property name="max" value="150"/>
|
||||
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
|
||||
</module>
|
||||
<module name="LocalFinalVariableName">
|
||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Final variable/parameter name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="LocalVariableName">
|
||||
<property name="allowOneCharVarInForLoop" value="true"/>
|
||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<!-- <module name="MagicNumber"/> -->
|
||||
<module name="MemberName">
|
||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Member name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<!-- <module name="MethodCount"/> -->
|
||||
<module name="MethodLength">
|
||||
<property name="max" value="40"/>
|
||||
</module>
|
||||
<module name="MethodName">
|
||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Method name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="MethodParamPad"/>
|
||||
<module name="MethodTypeParameterName">
|
||||
<property name="format" value="^[T]([A-Z][a-zA-Z0-9]*)?$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Method type name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<!-- <module name="MissingCtor"/> -->
|
||||
<!-- <module name="MissingDeprecated"/> -->
|
||||
<module name="MissingOverride"/>
|
||||
<module name="MissingSwitchDefault"/>
|
||||
<!-- <module name="ModifiedControlVariable"/> -->
|
||||
<module name="ModifierOrder"/>
|
||||
<!-- <module name="MultipleStringLiterals"/> -->
|
||||
<module name="MultipleVariableDeclarations"/>
|
||||
<module name="MutableException"/>
|
||||
<module name="NeedBraces"/>
|
||||
<!-- <module name="NestedForDepth"/> -->
|
||||
<!-- <module name="NestedIfDepth"/> -->
|
||||
<!-- <module name="NestedTryDepth"/> -->
|
||||
<!-- <module name="NewlineAtEndOfFile"/> -->
|
||||
<module name="NoClone"/>
|
||||
<module name="NoFinalizer"/>
|
||||
<module name="NoLineWrap"/>
|
||||
<module name="NonEmptyAtclauseDescription"/>
|
||||
<module name="NoWhitespaceAfter">
|
||||
<property name="tokens"
|
||||
value="ARRAY_INIT, INC, DEC, UNARY_MINUS, UNARY_PLUS, BNOT, LNOT, DOT, ARRAY_DECLARATOR, INDEX_OP"/>
|
||||
</module>
|
||||
<module name="NoWhitespaceBefore">
|
||||
<property name="tokens" value="COMMA, SEMI, POST_INC, POST_DEC, GENERIC_END"/>
|
||||
</module>
|
||||
<!-- <module name="NPathComplexity"/> -->
|
||||
<module name="OneStatementPerLine"/>
|
||||
<module name="OneTopLevelClass"/>
|
||||
<module name="OperatorWrap">
|
||||
<property name="option" value="NL"/>
|
||||
<property name="tokens"
|
||||
value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR "/>
|
||||
</module>
|
||||
<module name="OuterTypeFilename"/>
|
||||
<!-- <module name="OuterTypeNumber"/> -->
|
||||
<module name="OverloadMethodsDeclarationOrder"/>
|
||||
<!-- <module name="PackageAnnotation"/> -->
|
||||
<!-- <module name="PackageDeclaration"/> -->
|
||||
<module name="PackageName">
|
||||
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Package name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="ParameterAssignment"/>
|
||||
<module name="ParameterName">
|
||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<!-- <module name="ParameterNumber"/> -->
|
||||
<!-- <module name="ParenPad"/> -->
|
||||
<module name="RedundantImport"/>
|
||||
<!-- <module name="RedundantModifier"/> -->
|
||||
<!-- <module name="Regexp"/> -->
|
||||
<!-- <module name="RegexpHeader"/> -->
|
||||
<!-- <module name="RegexpMultiline"/> -->
|
||||
<!-- <module name="RegexpOnFilename"/> -->
|
||||
<!-- <module name="RegexpSingleline"/> -->
|
||||
<!-- <module name="RegexpSinglelineJava"/> -->
|
||||
<!-- <module name="ReturnCount"/> -->
|
||||
<module name="RequireThis">
|
||||
<property name="checkMethods" value="false"/>
|
||||
</module>
|
||||
<module name="RightCurly"/>
|
||||
<module name="RightCurly">
|
||||
<property name="option" value="alone"/>
|
||||
<property name="tokens" value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, LITERAL_DO, STATIC_INIT, INSTANCE_INIT"/>
|
||||
</module>
|
||||
<module name="SeparatorWrap">
|
||||
<property name="tokens" value="DOT"/>
|
||||
<property name="option" value="nl"/>
|
||||
</module>
|
||||
<module name="SeparatorWrap">
|
||||
<property name="tokens" value="COMMA"/>
|
||||
<property name="option" value="EOL"/>
|
||||
</module>
|
||||
<module name="SimplifyBooleanExpression"/>
|
||||
<module name="SimplifyBooleanReturn"/>
|
||||
<module name="SingleLineJavadoc"/>
|
||||
<module name="SingleSpaceSeparator"/>
|
||||
<module name="StaticVariableName">
|
||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Static variable name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="StringLiteralEquality"/>
|
||||
<module name="SummaryJavadoc">
|
||||
<property name="forbiddenSummaryFragments" value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
|
||||
</module>
|
||||
<!-- <module name="SuperClone"/> -->
|
||||
<!-- <module name="SuperFinalize"/> -->
|
||||
<!-- <module name="SuppressWarnings"/> -->
|
||||
<module name="SuppressWarningsHolder"/>
|
||||
<!-- <module name="ThrowsCount"/> -->
|
||||
<!-- <module name="TodoComment"/> -->
|
||||
<!-- <module name="TrailingComment"/> -->
|
||||
<!-- <module name="Translation"/> -->
|
||||
<!-- <module name="TypecastParenPad"/> -->
|
||||
<module name="TypeName">
|
||||
<message key="name.invalidPattern"
|
||||
value="Type name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<!-- <module name="UncommentedMain"/> -->
|
||||
<!-- <module name="UniqueProperties"/> -->
|
||||
<module name="UnnecessaryParentheses">
|
||||
<property name="tokens"
|
||||
value=" EXPR, IDENT, NUM_DOUBLE, NUM_FLOAT, NUM_INT, NUM_LONG, STRING_LITERAL, LITERAL_NULL, LITERAL_FALSE, LITERAL_TRUE, ASSIGN, BAND_ASSIGN, BOR_ASSIGN, BSR_ASSIGN, BXOR_ASSIGN, DIV_ASSIGN, MINUS_ASSIGN, MOD_ASSIGN, PLUS_ASSIGN, SL_ASSIGN, SR_ASSIGN, STAR_ASSIGN"/>
|
||||
</module>
|
||||
<module name="UnusedImports"/>
|
||||
<module name="UpperEll"/>
|
||||
<module name="VariableDeclarationUsageDistance"/>
|
||||
<!-- <module name="VisibilityModifier"/> -->
|
||||
<!-- <module name="WhitespaceAfter"/> -->
|
||||
<module name="WhitespaceAround">
|
||||
<property name="allowEmptyConstructors" value="true"/>
|
||||
<property name="allowEmptyMethods" value="true"/>
|
||||
<property name="allowEmptyTypes" value="true"/>
|
||||
<property name="allowEmptyLoops" value="true"/>
|
||||
<message key="ws.notFollowed"
|
||||
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
|
||||
<message key="ws.notPreceded"
|
||||
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
|
||||
</module>
|
||||
<!-- <module name="WriteTag"/> -->
|
||||
</module>
|
||||
|
||||
<module name="SuppressWarningsFilter"/>
|
||||
|
||||
|
||||
</module>
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
PROJECT_NAME=$1
|
||||
SRC_FOLDER_NAME=${PROJECT_NAME}-src-$(date +%F)
|
||||
SRC_DIR=./${SRC_FOLDER_NAME}
|
||||
|
||||
COMMAND_LINE_ARGUMENTS=$@
|
||||
|
||||
clone_platform() {
|
||||
PROJECT_DIR=$1
|
||||
PLATFORM=$2
|
||||
|
||||
git clone --recurse-submodules -j8 git@github.com:TouchInstinct/${PROJECT_DIR}-${PLATFORM}.git --branch master
|
||||
}
|
||||
|
||||
mkdir -p ${SRC_DIR}
|
||||
cd ${SRC_DIR}
|
||||
|
||||
for argument in ${COMMAND_LINE_ARGUMENTS}
|
||||
do
|
||||
if [ $argument != $PROJECT_NAME ]
|
||||
then
|
||||
platform=${argument} # all arguments after project name treated as platforms
|
||||
clone_platform ${PROJECT_NAME} ${platform}
|
||||
fi
|
||||
done
|
||||
|
||||
find . -name ".git*" -print0 | xargs -0 rm -rf
|
||||
zip -r ${SRC_FOLDER_NAME}.zip .
|
||||
|
||||
open .
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<FindBugsFilter>
|
||||
<Match>
|
||||
<!-- ignore all issues in resource generation -->
|
||||
<Class name="~.*\.R\$.*"/>
|
||||
</Match>
|
||||
<Match>
|
||||
<Class name="~.*\.Manifest\$.*"/>
|
||||
</Match>
|
||||
<Match>
|
||||
<!-- ignore concrete check groups -->
|
||||
<Bug code="DP"/>
|
||||
</Match>
|
||||
<Match>
|
||||
<!-- ignore concrete checks -->
|
||||
<Bug pattern="BC_UNCONFIRMED_CAST_OF_RETURN_VALUE, NP_UNWRITTEN_FIELD, UWF_NULL_FIELD, UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR, PZLA_PREFER_ZERO_LENGTH_ARRAYS, EI_EXPOSE_REP, EI_EXPOSE_REP2, REC_CATCH_EXCEPTION, EQ_COMPARETO_USE_OBJECT_EQUALS, BC_UNCONFIRMED_CAST, EQ_DOESNT_OVERRIDE_EQUALS, BC_IMPOSSIBLE_CAST" />
|
||||
</Match>
|
||||
<Match>
|
||||
<Bug code="UPM" />
|
||||
<Class name="~.*\$\$Lambda\$.*"/>
|
||||
</Match>
|
||||
|
||||
</FindBugsFilter>
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
repositories {
|
||||
maven {
|
||||
url 'https://dl.bintray.com/touchin/touchin-tools'
|
||||
metadataSources {
|
||||
artifact()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
apigenerator
|
||||
}
|
||||
|
||||
dependencies {
|
||||
apigenerator 'ru.touchin:api-generator:1.4.0-beta1'
|
||||
}
|
||||
|
||||
android.applicationVariants.all { variant ->
|
||||
final File generatedModelsDirectory = new File("${project.buildDir}/generated/source/models/${variant.dirName}")
|
||||
|
||||
def generateJsonModelsTask = tasks.create("apiGenerator${variant.name}") doLast {
|
||||
javaexec {
|
||||
main = "-jar"
|
||||
workingDir = file("${rootDir}")
|
||||
args = [
|
||||
configurations.apigenerator.asPath,
|
||||
"generate-client-code",
|
||||
"--output-language",
|
||||
"JAVA",
|
||||
"--specification-path",
|
||||
rootProject.extensions.findByName("pathToApiSchemes"),
|
||||
"--output-path",
|
||||
"${generatedModelsDirectory.path}",
|
||||
"--package-name",
|
||||
"${rootProject.extensions.findByName("applicationId") ?: applicationId}"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
generateJsonModelsTask.description = 'Generates Java classes for JSON models'
|
||||
variant.registerJavaGeneratingTask generateJsonModelsTask, generatedModelsDirectory
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
repositories {
|
||||
maven {
|
||||
url "https://dl.bintray.com/touchin/touchin-tools"
|
||||
metadataSources {
|
||||
artifact()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
apigeneratorKotlinServer
|
||||
}
|
||||
|
||||
dependencies {
|
||||
apigeneratorKotlinServer 'ru.touchin:api-generator:1.4.0-beta1'
|
||||
}
|
||||
|
||||
task generateApiModelsKotlinServer doLast {
|
||||
javaexec {
|
||||
main = "-jar"
|
||||
workingDir = file("${rootDir}")
|
||||
args = [
|
||||
configurations.apigeneratorKotlinServer.asPath,
|
||||
"generate-client-code",
|
||||
"--output-language",
|
||||
"KOTLIN_SERVER",
|
||||
"--specification-path",
|
||||
rootProject.extensions.findByName("pathToApiSchemes"),
|
||||
"--output-path",
|
||||
"${rootDir}/src/main/kotlin",
|
||||
"--package-name",
|
||||
rootProject.extensions.findByName("apiPackageName"),
|
||||
"--recreate_output_dirs",
|
||||
false
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,233 +0,0 @@
|
|||
apply plugin: 'cpd'
|
||||
apply plugin: 'io.gitlab.arturbosch.detekt'
|
||||
|
||||
def getCpdTask
|
||||
def getLintTask
|
||||
def getKotlinDetektTasks
|
||||
|
||||
def appendError
|
||||
def appendCpdErrors
|
||||
def appendKotlinErrors
|
||||
def appendLintErrors
|
||||
|
||||
repositories {
|
||||
maven { url "http://dl.bintray.com/touchin/touchin-tools" }
|
||||
}
|
||||
|
||||
configurations {
|
||||
pngtastic
|
||||
}
|
||||
|
||||
cpd {
|
||||
skipLexicalErrors = true
|
||||
}
|
||||
|
||||
import org.apache.tools.ant.taskdefs.condition.Os
|
||||
|
||||
ext.getIdeaFormatTask = { isAndroidProject, sources ->
|
||||
def ideaPath = System.getenv("IDEA_HOME")
|
||||
if (ideaPath == null) {
|
||||
return tasks.create((isAndroidProject ? "android" : "server") + "donothing")
|
||||
}
|
||||
return tasks.create((isAndroidProject ? "android" : "server") + "IdeaFormat_$project.name", Exec) {
|
||||
def inspectionPath
|
||||
def params = ["-r", "-mask", "*.java,*.kt,*.xml"]
|
||||
for (String source : sources) {
|
||||
params.add(source)
|
||||
}
|
||||
|
||||
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||
inspectionPath = ['cmd', '/c', "\"${ideaPath}\\bin\\format.bat\" ${params.join(" ")}"]
|
||||
} else {
|
||||
inspectionPath = ["$ideaPath/bin/format.sh"]
|
||||
}
|
||||
commandLine inspectionPath
|
||||
if (!Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||
args = params
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ext.getStaticAnalysisTaskNames = { isAndroidProject, sources, buildVariant ->
|
||||
def tasksNames = new ArrayList<String>()
|
||||
try {
|
||||
tasksNames.add(getCpdTask(isAndroidProject, sources))
|
||||
tasksNames.addAll(getKotlinDetektTasks())
|
||||
if (isAndroidProject) {
|
||||
tasksNames.add(getLintTask(buildVariant))
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
println(exception.toString())
|
||||
}
|
||||
return tasksNames
|
||||
}
|
||||
|
||||
ext.generateReport = { isAndroidProject ->
|
||||
StringBuilder consoleReport = new StringBuilder()
|
||||
consoleReport.append("STATIC ANALYSIS RESULTS:")
|
||||
def count = 0
|
||||
|
||||
def previousCount = count
|
||||
count = appendCpdErrors(count, new File("${project.buildDir}/reports/cpd.xml"))
|
||||
if (count - previousCount > 0) {
|
||||
consoleReport.append("\nCPD: FAILED (" + (count - previousCount) + " errors)")
|
||||
} else {
|
||||
consoleReport.append("\nCPD: PASSED")
|
||||
}
|
||||
|
||||
previousCount = count
|
||||
subprojects.forEach { subproject ->
|
||||
def reportFile = new File("${rootProject.buildDir}/reports/kotlin-detekt-${subproject.name}.xml")
|
||||
if (reportFile.exists()) {
|
||||
count = appendKotlinErrors(count, reportFile).toInteger()
|
||||
}
|
||||
}
|
||||
if (count - previousCount > 0) {
|
||||
consoleReport.append("\nKotlin-detekt: FAILED (" + (count - previousCount) + " errors)")
|
||||
} else {
|
||||
consoleReport.append("\nKotlin-detekt: PASSED")
|
||||
}
|
||||
|
||||
if (isAndroidProject) {
|
||||
previousCount = count
|
||||
count = appendLintErrors(count, new File("${rootProject.buildDir}/reports/lint_report.xml"))
|
||||
if (count - previousCount > 0) {
|
||||
consoleReport.append("\nLint: FAILED (" + (count - previousCount) + " errors)")
|
||||
} else {
|
||||
consoleReport.append("\nLint: PASSED")
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
consoleReport.append("\nOverall: FAILED (" + count + " errors)")
|
||||
throw new Exception(consoleReport.toString())
|
||||
} else {
|
||||
consoleReport.append("\nOverall: PASSED")
|
||||
println(consoleReport.toString())
|
||||
}
|
||||
}
|
||||
|
||||
appendError = { number, analyzer, file, line, errorId, errorLink, description ->
|
||||
println("$number. $analyzer : $description ($errorId)\n\tat $file: $line")
|
||||
}
|
||||
|
||||
appendKotlinErrors = { count, checkstyleFile ->
|
||||
def rootNode = new XmlParser().parse(checkstyleFile)
|
||||
for (def fileNode : rootNode.children()) {
|
||||
if (!fileNode.name().equals("file")) {
|
||||
continue
|
||||
}
|
||||
|
||||
for (def errorNode : fileNode.children()) {
|
||||
if (!errorNode.name().equals("error")) {
|
||||
continue
|
||||
}
|
||||
count++
|
||||
|
||||
appendError(count, "Detekt", fileNode.attribute("name"), errorNode.attribute("line"), errorNode.attribute("source"), "", errorNode.attribute("message"))
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
appendCpdErrors = { count, cpdFile ->
|
||||
def rootNode = new XmlParser().parse(cpdFile)
|
||||
for (def duplicationNode : rootNode.children()) {
|
||||
if (!duplicationNode.name().equals("duplication")) {
|
||||
continue
|
||||
}
|
||||
count++
|
||||
|
||||
def duplicationIndex = 0
|
||||
|
||||
String duplicationPoints = ""
|
||||
for (def filePointNode : duplicationNode.children()) {
|
||||
if (filePointNode.name().equals("file")) {
|
||||
def file = filePointNode.attribute("path")
|
||||
def line = filePointNode.attribute("line")
|
||||
duplicationPoints += "\n " + file + ":" + line
|
||||
duplicationIndex++
|
||||
}
|
||||
}
|
||||
println("$count CPD: code duplication $duplicationPoints")
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
appendLintErrors = { count, lintFile ->
|
||||
def rootNode = new XmlParser().parse(lintFile)
|
||||
for (def issueNode : rootNode.children()) {
|
||||
if (!issueNode.name().equals("issue")
|
||||
|| !issueNode.attribute("severity").equals("Error")) {
|
||||
continue
|
||||
}
|
||||
for (def locationNode : issueNode.children()) {
|
||||
if (!locationNode.name().equals("location")) {
|
||||
continue
|
||||
}
|
||||
count++
|
||||
appendError(count, "Lint", locationNode.attribute("file"), locationNode.attribute("line"),
|
||||
issueNode.attribute("id"), issueNode.attribute("explanation"), issueNode.attribute("message"))
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
getCpdTask = { isAndroidProject, sources ->
|
||||
def taskName = (isAndroidProject ? "android" : "server") + "cpd_${rootProject.name}"
|
||||
def task = tasks.findByName(taskName)
|
||||
if (task == null) {
|
||||
task = tasks.create(taskName, tasks.findByName('cpdCheck').getClass().getSuperclass()) {
|
||||
minimumTokenCount = 60
|
||||
source = files(sources)
|
||||
ignoreFailures = true
|
||||
reports {
|
||||
xml {
|
||||
enabled = true
|
||||
destination = file("${rootProject.buildDir}/reports/cpd.xml")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return task.path
|
||||
}
|
||||
|
||||
getLintTask = { buildVariant ->
|
||||
def appProject = subprojects.find { it.plugins.hasPlugin("com.android.application") }
|
||||
def lintTaskPath
|
||||
if (buildVariant != null) {
|
||||
lintTaskPath = ":${appProject.name}:lint${buildVariant.name.capitalize()}"
|
||||
} else {
|
||||
def lintDebugTasks = appProject.tasks.matching { it.getName().contains("lint") && it.getName().contains("Debug") }
|
||||
lintTaskPath = lintDebugTasks.first().path
|
||||
}
|
||||
if (lintTaskPath == null) {
|
||||
throw IllegalStateException("Unable to find lint debug task for build variant: ${buildVariant}")
|
||||
}
|
||||
return lintTaskPath
|
||||
}
|
||||
|
||||
getKotlinDetektTasks = {
|
||||
subprojects
|
||||
.findResults { it.tasks.findByName("detekt")?.path }
|
||||
.findAll { !it.contains(":libs") }
|
||||
}
|
||||
|
||||
task optimizePng {
|
||||
doFirst {
|
||||
def jarArgs = new ArrayList<String>()
|
||||
jarArgs.add(configurations.pngtastic.asPath)
|
||||
def relatedPathIndex = "${rootDir}".length() + 1
|
||||
for (def file : fileTree(dir: "${rootDir}", include: '**/src/**/res/drawable**/*.png')) {
|
||||
jarArgs.add(file.absolutePath.substring(relatedPathIndex))
|
||||
}
|
||||
for (def file : fileTree(dir: "${rootDir}", include: '**/src/**/res/mipmap**/*.png')) {
|
||||
jarArgs.add(file.absolutePath.substring(relatedPathIndex))
|
||||
}
|
||||
javaexec { main = "-jar"; args = jarArgs; workingDir = file("${rootDir}") }
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
pngtastic 'com.github.depsypher:pngtastic:1.2'
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
# Generated files
|
||||
bin/
|
||||
gen/
|
||||
|
||||
# Gradle files
|
||||
.gradle/
|
||||
build/
|
||||
/*/build/
|
||||
|
||||
# Local configuration file (sdk path, etc)
|
||||
local.properties
|
||||
|
||||
# Log Files
|
||||
*.log
|
||||
|
||||
.gradle
|
||||
.idea
|
||||
.DS_Store
|
||||
/captures
|
||||
*.iml
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
`java-gradle-plugin`
|
||||
`kotlin-dsl`
|
||||
}
|
||||
|
||||
// The kotlin-dsl plugin requires a repository to be declared
|
||||
repositories {
|
||||
jcenter()
|
||||
google()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// android gradle plugin, required by custom plugin
|
||||
implementation("com.android.tools.build:gradle:4.0.1")
|
||||
|
||||
implementation("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.10.0")
|
||||
implementation("de.aaschmid:gradle-cpd-plugin:3.1")
|
||||
|
||||
// kotlin plugin, required by custom plugin
|
||||
implementation(kotlin("gradle-plugin", embeddedKotlinVersion))
|
||||
|
||||
gradleKotlinDsl()
|
||||
implementation(kotlin("stdlib-jdk8"))
|
||||
}
|
||||
|
||||
val compileKotlin: KotlinCompile by tasks
|
||||
compileKotlin.kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
|
||||
gradlePlugin {
|
||||
plugins {
|
||||
create("api-generator-android") {
|
||||
id = "api-generator-android"
|
||||
implementationClass = "apigen.ApiGeneratorAndroidPlugin"
|
||||
}
|
||||
create("api-generator-backend") {
|
||||
id = "api-generator-backend"
|
||||
implementationClass = "apigen.ApiGeneratorBackendPlugin"
|
||||
}
|
||||
create("static-analysis-android") {
|
||||
id = "static-analysis-android"
|
||||
implementationClass = "static_analysis.plugins.StaticAnalysisAndroidPlugin"
|
||||
}
|
||||
create("static-analysis-backend") {
|
||||
id = "static-analysis-backend"
|
||||
implementationClass = "static_analysis.plugins.StaticAnalysisBackendPlugin"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package apigen
|
||||
|
||||
import com.android.build.gradle.AppExtension
|
||||
import com.android.build.gradle.LibraryExtension
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.compile.JavaCompile
|
||||
import org.gradle.kotlin.dsl.findByType
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
class ApiGeneratorAndroidPlugin : ApiGeneratorPlugin() {
|
||||
|
||||
override fun apply(target: Project) {
|
||||
super.apply(target)
|
||||
|
||||
with(target) {
|
||||
val extension = getExtension()
|
||||
val outputDir = getDirectoryForGeneration()
|
||||
|
||||
extension.outputDirPath = outputDir.path
|
||||
extension.recreateOutputDir = true
|
||||
|
||||
afterEvaluate {
|
||||
extensions.findByType<LibraryExtension>()?.apply {
|
||||
sourceSets.getByName("main")
|
||||
.java
|
||||
.srcDir(outputDir)
|
||||
}
|
||||
extensions.findByType<AppExtension>()?.apply {
|
||||
sourceSets.getByName("main")
|
||||
.java
|
||||
.srcDir(outputDir)
|
||||
}
|
||||
tasks
|
||||
.filterIsInstance<KotlinCompile>()
|
||||
.forEach { it.source(outputDir) }
|
||||
|
||||
tasks
|
||||
.filterIsInstance<JavaCompile>()
|
||||
.forEach { it.source(outputDir) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Project.getDirectoryForGeneration() = file("$buildDir/generated/api")
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package apigen
|
||||
|
||||
import org.gradle.api.Project
|
||||
|
||||
class ApiGeneratorBackendPlugin : ApiGeneratorPlugin() {
|
||||
|
||||
override fun apply(target: Project) {
|
||||
super.apply(target)
|
||||
|
||||
val extension = target.getExtension()
|
||||
|
||||
extension.outputDirPath = target.file("src/main/kotlin").path
|
||||
extension.recreateOutputDir = false
|
||||
extension.outputLanguage = OutputLanguage.KotlinServer
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package apigen
|
||||
|
||||
open class ApiGeneratorExtension(
|
||||
var pathToApiSchemes: String? = null,
|
||||
var outputPackageName: String = "",
|
||||
var outputDirPath: String = "",
|
||||
var recreateOutputDir: Boolean = false,
|
||||
var outputLanguage: OutputLanguage? = null
|
||||
)
|
||||
|
||||
sealed class OutputLanguage(val argName: String, val methodOutputType: MethodOutputType? = null) {
|
||||
object KotlinServer : OutputLanguage("KOTLIN_SERVER")
|
||||
class KotlinAndroid(methodOutputType: MethodOutputType = MethodOutputType.Rx) : OutputLanguage("KOTLIN", methodOutputType)
|
||||
object Java : OutputLanguage("JAVA")
|
||||
object Swift : OutputLanguage("SWIFT")
|
||||
}
|
||||
|
||||
sealed class MethodOutputType(val argName: String) {
|
||||
object Rx : MethodOutputType("REACTIVE")
|
||||
object RetrofitCall : MethodOutputType("CALL")
|
||||
object Coroutine : MethodOutputType("COROUTINE")
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
package apigen
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.kotlin.dsl.create
|
||||
import org.gradle.kotlin.dsl.dependencies
|
||||
import org.gradle.kotlin.dsl.repositories
|
||||
|
||||
abstract class ApiGeneratorPlugin : Plugin<Project> {
|
||||
|
||||
companion object {
|
||||
const val API_GENERATOR_CONFIG = "apiGenerator"
|
||||
const val API_GENERATOR_EXT_NAME = "apiGenerator"
|
||||
const val API_GENERATOR_DEFAULT_VERSION = "1.4.0-beta10"
|
||||
}
|
||||
|
||||
override fun apply(target: Project) {
|
||||
with(target) {
|
||||
repositories {
|
||||
maven {
|
||||
url = uri("https://maven.dev.touchin.ru")
|
||||
metadataSources {
|
||||
artifact()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configurations.create(API_GENERATOR_CONFIG)
|
||||
|
||||
dependencies {
|
||||
add(API_GENERATOR_CONFIG, "ru.touchin:api-generator:$API_GENERATOR_DEFAULT_VERSION")
|
||||
}
|
||||
|
||||
extensions.create<ApiGeneratorExtension>(API_GENERATOR_EXT_NAME)
|
||||
|
||||
val apiGenTask = createApiGeneratorTask()
|
||||
|
||||
gradle.projectsEvaluated {
|
||||
tasks.getByName("preBuild").dependsOn(apiGenTask)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun Project.getExtension(): ApiGeneratorExtension = extensions.getByName(API_GENERATOR_EXT_NAME) as ApiGeneratorExtension
|
||||
|
||||
private fun Project.createApiGeneratorTask(): Task = tasks.create(API_GENERATOR_CONFIG).doLast {
|
||||
|
||||
val extension = getExtension()
|
||||
|
||||
val pathToApiSchemes = extension.pathToApiSchemes ?: throw IllegalStateException("Configure path to api schemes for api generator plugin")
|
||||
val outputLanguage = extension.outputLanguage ?: throw IllegalStateException("Configure output language code for api generator plugin")
|
||||
|
||||
javaexec {
|
||||
main = "-jar"
|
||||
workingDir = rootDir
|
||||
args = listOfNotNull(
|
||||
configurations.getByName("apiGenerator").asPath,
|
||||
"generate-client-code",
|
||||
"--output-language",
|
||||
outputLanguage.argName,
|
||||
"--specification-path",
|
||||
pathToApiSchemes,
|
||||
"--kotlin-methods-generation-mode".takeIf { outputLanguage.methodOutputType != null },
|
||||
outputLanguage.methodOutputType?.argName,
|
||||
"--output-path",
|
||||
extension.outputDirPath,
|
||||
"--package-name",
|
||||
extension.outputPackageName,
|
||||
"--recreate_output_dirs",
|
||||
extension.recreateOutputDir.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package static_analysis.errors
|
||||
|
||||
class AndroidLintError(
|
||||
private val filePath: String,
|
||||
private val fileLine: String?,
|
||||
private val errorId: String,
|
||||
private val description: String
|
||||
) : StaticAnalysisError {
|
||||
|
||||
override fun print(count: Int): String = "\n$count. Android Lint. $description ($errorId)\n\tat [$filePath$fileLinePrefix]"
|
||||
|
||||
private val fileLinePrefix: String
|
||||
get() = fileLine?.let { ":$it" }.orEmpty()
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package static_analysis.errors
|
||||
|
||||
class CpdError(
|
||||
private val duplications: List<Pair<String, String>>,
|
||||
private val codeFragment: String
|
||||
) : StaticAnalysisError {
|
||||
|
||||
override fun print(count: Int): String = "\n$count. CPD. Code duplication in files: " +
|
||||
duplications.joinToString(separator = "") { (file, line) -> "\n\t[$file:$line]" } +
|
||||
"\n\n Duplicated code:\n\n$codeFragment\n"
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package static_analysis.errors
|
||||
|
||||
class DetektError(
|
||||
private val filePath: String,
|
||||
private val fileLine: String,
|
||||
private val errorId: String,
|
||||
private val description: String
|
||||
) : StaticAnalysisError {
|
||||
|
||||
override fun print(count: Int): String = "\n$count. Detekt. $description ($errorId)\n\tat [$filePath:$fileLine]"
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package static_analysis.errors
|
||||
|
||||
interface StaticAnalysisError {
|
||||
fun print(count: Int): String
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
package static_analysis.linters
|
||||
|
||||
import com.android.build.gradle.AppExtension
|
||||
import com.android.build.gradle.AppPlugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.kotlin.dsl.findByType
|
||||
import static_analysis.errors.AndroidLintError
|
||||
import static_analysis.errors.StaticAnalysisError
|
||||
import static_analysis.plugins.StaticAnalysisExtension
|
||||
import static_analysis.utils.typedChildren
|
||||
import static_analysis.utils.xmlParser
|
||||
|
||||
class AndroidLinter : Linter {
|
||||
|
||||
override val name: String = "Android lint"
|
||||
|
||||
override fun getErrors(project: Project): List<StaticAnalysisError> = xmlParser(project.getLintReportFile())
|
||||
.typedChildren()
|
||||
.filter { it.name() == "issue" && (it.attribute("severity") as String) == "Error" }
|
||||
.map { errorNode ->
|
||||
errorNode
|
||||
.typedChildren()
|
||||
.filter { it.name() == "location" }
|
||||
.map { locationNode ->
|
||||
AndroidLintError(
|
||||
filePath = locationNode.attribute("file") as String,
|
||||
fileLine = locationNode.attribute("line") as String?,
|
||||
errorId = errorNode.attribute("id") as String,
|
||||
description = errorNode.attribute("message") as String
|
||||
)
|
||||
}
|
||||
}
|
||||
.flatten()
|
||||
|
||||
override fun setupForProject(project: Project, extension: StaticAnalysisExtension) {
|
||||
project.gradle.projectsEvaluated {
|
||||
project.subprojects
|
||||
.mapNotNull { it.extensions.findByType<AppExtension>() }
|
||||
.first()
|
||||
.lintOptions.apply {
|
||||
isAbortOnError = false
|
||||
isCheckAllWarnings = true
|
||||
isWarningsAsErrors = false
|
||||
xmlReport = true
|
||||
htmlReport = false
|
||||
isCheckDependencies = true
|
||||
disable("MissingConstraints", "VectorRaster")
|
||||
xmlOutput = project.getLintReportFile()
|
||||
lintConfig = project.file("${extension.buildScriptDir}/static_analysis_configs/lint.xml")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getTaskNames(project: Project, buildType: String?): List<String> {
|
||||
if (buildType == null) {
|
||||
throw IllegalStateException("Build type must not be null in android linter")
|
||||
}
|
||||
|
||||
return project
|
||||
.subprojects
|
||||
.filter { it.plugins.hasPlugin(AppPlugin::class.java) }
|
||||
.mapNotNull { subproject: Project ->
|
||||
subproject
|
||||
.tasks
|
||||
.find { task -> task.name.contains(buildType, ignoreCase = true) && task.name.contains("lint") }
|
||||
?.path
|
||||
}
|
||||
}
|
||||
|
||||
private fun Project.getLintReportFile() = file("${rootProject.buildDir}/reports/lint-report.xml")
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
package static_analysis.linters
|
||||
|
||||
import de.aaschmid.gradle.plugins.cpd.Cpd
|
||||
import de.aaschmid.gradle.plugins.cpd.CpdExtension
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.kotlin.dsl.findByType
|
||||
import org.gradle.kotlin.dsl.withType
|
||||
import static_analysis.errors.CpdError
|
||||
import static_analysis.errors.StaticAnalysisError
|
||||
import static_analysis.plugins.StaticAnalysisExtension
|
||||
import static_analysis.utils.getSources
|
||||
import static_analysis.utils.typedChildren
|
||||
import static_analysis.utils.xmlParser
|
||||
|
||||
class CpdLinter : Linter {
|
||||
|
||||
override val name: String = "CPD"
|
||||
|
||||
override fun getErrors(project: Project): List<StaticAnalysisError> = xmlParser(project.getCpdReportFile())
|
||||
.typedChildren()
|
||||
.filter { it.name() == "duplication" }
|
||||
.map { duplicationNode ->
|
||||
|
||||
val children = duplicationNode
|
||||
.typedChildren()
|
||||
|
||||
CpdError(
|
||||
duplications = children
|
||||
.filter { it.name() == "file" }
|
||||
.map { fileNode -> fileNode.attribute("path") as String to fileNode.attribute("line") as String },
|
||||
codeFragment = children.findLast { it.name() == "codefragment" }!!.text()
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
override fun setupForProject(project: Project, extension: StaticAnalysisExtension) {
|
||||
project.extensions.findByType<CpdExtension>()!!.apply {
|
||||
isSkipLexicalErrors = true
|
||||
language = "kotlin"
|
||||
minimumTokenCount = 60
|
||||
}
|
||||
project.tasks.withType<Cpd> {
|
||||
reports.xml.destination = project.getCpdReportFile()
|
||||
ignoreFailures = true
|
||||
source = project.getSources(extension.excludes)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getTaskNames(project: Project, buildType: String?): List<String> = project
|
||||
.rootProject
|
||||
.tasks
|
||||
.withType<Cpd>()
|
||||
.map(Cpd::getPath)
|
||||
|
||||
private fun Project.getCpdReportFile() = file("${rootProject.buildDir}/reports/cpd.xml")
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
package static_analysis.linters
|
||||
|
||||
import io.gitlab.arturbosch.detekt.Detekt
|
||||
import org.gradle.api.Project
|
||||
import static_analysis.errors.DetektError
|
||||
import static_analysis.errors.StaticAnalysisError
|
||||
import static_analysis.plugins.StaticAnalysisExtension
|
||||
import static_analysis.utils.getSources
|
||||
import static_analysis.utils.typedChildren
|
||||
import static_analysis.utils.xmlParser
|
||||
|
||||
class DetektLinter : Linter {
|
||||
|
||||
override val name: String = "Detekt"
|
||||
|
||||
override fun getErrors(project: Project): List<StaticAnalysisError> = xmlParser(project.getDetektReportFile())
|
||||
.typedChildren()
|
||||
.filter { fileNode -> fileNode.name() == "file" }
|
||||
.map { fileNode ->
|
||||
fileNode
|
||||
.typedChildren()
|
||||
.filter { it.name() == "error" }
|
||||
.map { errorNode ->
|
||||
DetektError(
|
||||
filePath = fileNode.attribute("name") as String,
|
||||
fileLine = errorNode.attribute("line") as String,
|
||||
errorId = errorNode.attribute("source") as String,
|
||||
description = errorNode.attribute("message") as String
|
||||
)
|
||||
}
|
||||
}
|
||||
.flatten()
|
||||
|
||||
override fun setupForProject(project: Project, extension: StaticAnalysisExtension) {
|
||||
project
|
||||
.tasks
|
||||
.withType(Detekt::class.java) {
|
||||
exclude("**/test/**")
|
||||
exclude("resources/")
|
||||
exclude("build/")
|
||||
exclude("tmp/")
|
||||
jvmTarget = "1.8"
|
||||
|
||||
config.setFrom(project.files("${extension.buildScriptDir!!}/static_analysis_configs/detekt-config.yml"))
|
||||
reports {
|
||||
txt.enabled = false
|
||||
html.enabled = false
|
||||
xml {
|
||||
enabled = true
|
||||
destination = project.getDetektReportFile()
|
||||
}
|
||||
}
|
||||
|
||||
source = project.getSources(extension.excludes)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getTaskNames(project: Project, buildType: String?): List<String> = listOf(":detekt")
|
||||
|
||||
private fun Project.getDetektReportFile() = file("${rootProject.buildDir}/reports/detekt.xml")
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package static_analysis.linters
|
||||
|
||||
import org.gradle.api.Project
|
||||
import static_analysis.errors.StaticAnalysisError
|
||||
import static_analysis.plugins.StaticAnalysisExtension
|
||||
|
||||
interface Linter {
|
||||
val name: String
|
||||
fun getErrors(project: Project): List<StaticAnalysisError>
|
||||
fun setupForProject(project: Project, extension: StaticAnalysisExtension)
|
||||
fun getTaskNames(project: Project, buildType: String? = null): List<String>
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package static_analysis.plugins
|
||||
|
||||
import com.android.build.gradle.AppExtension
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.kotlin.dsl.getByType
|
||||
import static_analysis.linters.AndroidLinter
|
||||
import static_analysis.linters.CpdLinter
|
||||
import static_analysis.linters.DetektLinter
|
||||
import static_analysis.linters.Linter
|
||||
|
||||
class StaticAnalysisAndroidPlugin : StaticAnalysisPlugin() {
|
||||
|
||||
override fun createStaticAnalysisTasks(project: Project, linters: List<Linter>) {
|
||||
project.subprojects {
|
||||
if (plugins.hasPlugin("com.android.application")) {
|
||||
|
||||
extensions.getByType<AppExtension>().apply {
|
||||
applicationVariants.forEach { variant ->
|
||||
project.tasks.register("staticAnalysis${variant.name.capitalize()}") {
|
||||
setupStaticAnalysisTask(linters, variant.name)
|
||||
}
|
||||
}
|
||||
|
||||
project.tasks.register("staticAnalysis") {
|
||||
setupStaticAnalysisTask(
|
||||
linters = linters,
|
||||
buildVariant = applicationVariants.first { it.name.contains("Debug") }.name
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun createLinters(): List<Linter> = listOf(
|
||||
DetektLinter(),
|
||||
CpdLinter(),
|
||||
AndroidLinter()
|
||||
)
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package static_analysis.plugins
|
||||
|
||||
import org.gradle.api.Project
|
||||
import static_analysis.linters.CpdLinter
|
||||
import static_analysis.linters.DetektLinter
|
||||
import static_analysis.linters.Linter
|
||||
|
||||
class StaticAnalysisBackendPlugin : StaticAnalysisPlugin() {
|
||||
|
||||
override fun createStaticAnalysisTasks(project: Project, linters: List<Linter>) {
|
||||
project.tasks.register("staticAnalysis") {
|
||||
setupStaticAnalysisTask(linters)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createLinters(): List<Linter> = listOf(
|
||||
CpdLinter(),
|
||||
DetektLinter()
|
||||
)
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package static_analysis.plugins
|
||||
|
||||
open class StaticAnalysisExtension(
|
||||
var excludes: String = "",
|
||||
var buildScriptDir: String? = null
|
||||
)
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
package static_analysis.plugins
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.kotlin.dsl.create
|
||||
import org.gradle.kotlin.dsl.getByType
|
||||
import static_analysis.linters.Linter
|
||||
import static_analysis.utils.ReportGenerator
|
||||
|
||||
abstract class StaticAnalysisPlugin : Plugin<Project> {
|
||||
|
||||
companion object {
|
||||
const val DETEKT_ID = "io.gitlab.arturbosch.detekt"
|
||||
const val CPD_ID = "de.aaschmid.cpd"
|
||||
const val STATIC_ANALYSIS_EXT_NAME = "staticAnalysis"
|
||||
}
|
||||
|
||||
override fun apply(target: Project) {
|
||||
|
||||
with(target) {
|
||||
pluginManager.apply(CPD_ID)
|
||||
pluginManager.apply(DETEKT_ID)
|
||||
|
||||
extensions.create<StaticAnalysisExtension>(STATIC_ANALYSIS_EXT_NAME)
|
||||
|
||||
val linters = createLinters()
|
||||
|
||||
afterEvaluate {
|
||||
linters.forEach { it.setupForProject(target, extensions.getByType()) }
|
||||
}
|
||||
|
||||
gradle.projectsEvaluated {
|
||||
createStaticAnalysisTasks(target, linters)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Task.setupStaticAnalysisTask(linters: List<Linter>, buildVariant: String? = null) {
|
||||
doFirst { ReportGenerator.generate(linters, project) }
|
||||
dependsOn(*(linters.map { it.getTaskNames(project, buildVariant) }.flatten().toTypedArray()))
|
||||
}
|
||||
|
||||
abstract fun createLinters(): List<Linter>
|
||||
abstract fun createStaticAnalysisTasks(project: Project, linters: List<Linter>)
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package static_analysis.utils
|
||||
|
||||
import groovy.util.Node
|
||||
|
||||
fun Node.typedChildren() = children() as List<Node>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package static_analysis.utils
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.FileTree
|
||||
import java.io.File
|
||||
|
||||
fun Project.getSources(excludes: String): FileTree = files(
|
||||
project
|
||||
.rootProject
|
||||
.subprojects
|
||||
.filter { subproject -> subproject.subprojects.isEmpty() && !excludes.contains(subproject.path) }
|
||||
.map { subproject -> subproject.file("${subproject.projectDir.path}/src/main") }
|
||||
.filter { it.exists() && it.isDirectory }
|
||||
.flatMap { srcDir ->
|
||||
srcDir
|
||||
.listFiles()
|
||||
.orEmpty()
|
||||
.flatMap {
|
||||
listOf(
|
||||
File(srcDir.path, "java"),
|
||||
File(srcDir.path, "kotlin")
|
||||
)
|
||||
}
|
||||
}
|
||||
.filter { it.exists() && it.isDirectory }
|
||||
.map { it.path }
|
||||
).asFileTree
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package static_analysis.utils
|
||||
|
||||
import org.gradle.api.Project
|
||||
import static_analysis.errors.StaticAnalysisError
|
||||
import static_analysis.linters.Linter
|
||||
|
||||
object ReportGenerator {
|
||||
|
||||
fun generate(linters: List<Linter>, project: Project) {
|
||||
|
||||
val groupedErrors = linters
|
||||
.map { linter -> linter to linter.getErrors(project) }
|
||||
|
||||
val lintersResults = groupedErrors
|
||||
.map { (linter, linterErrors) -> linter.name to linterErrors.size }
|
||||
|
||||
val allErrors = groupedErrors
|
||||
.map(Pair<Linter, List<StaticAnalysisError>>::second)
|
||||
.flatten()
|
||||
|
||||
val consoleReport = StringBuilder("\nSTATIC ANALYSIS ERRORS:").apply {
|
||||
appendAllErrors(allErrors)
|
||||
append("\nREPORT:\n")
|
||||
appendReportsSummary(lintersResults)
|
||||
appendOverallSummary(allErrors)
|
||||
}
|
||||
|
||||
if (allErrors.isEmpty()) {
|
||||
println(consoleReport)
|
||||
} else {
|
||||
throw Exception(consoleReport.toString())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun StringBuilder.appendAllErrors(errors: List<StaticAnalysisError>) = errors
|
||||
.mapIndexed { index, staticAnalysisError -> staticAnalysisError.print(index + 1) }
|
||||
.forEach { error -> append(error) }
|
||||
|
||||
private fun StringBuilder.appendReportsSummary(lintersResults: List<Pair<String, Int>>) = lintersResults
|
||||
.forEach { this.appendSummary(it.first, it.second) }
|
||||
|
||||
private fun StringBuilder.appendOverallSummary(errors: List<StaticAnalysisError>) = appendSummary("Overall", errors.size)
|
||||
|
||||
private fun StringBuilder.appendSummary(header: String, quantityOfErrors: Int) {
|
||||
assert(quantityOfErrors < 0)
|
||||
|
||||
append("\n$header: ")
|
||||
append(if (quantityOfErrors == 0) "PASSED" else "FAILED ($quantityOfErrors errors)")
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package static_analysis.utils
|
||||
|
||||
import groovy.util.XmlParser
|
||||
import java.io.File
|
||||
|
||||
fun xmlParser(file: File) = XmlParser().parse(file)
|
||||
|
|
@ -2,11 +2,11 @@ import groovy.json.JsonSlurper
|
|||
import groovy.xml.MarkupBuilder
|
||||
|
||||
task stringGenerator {
|
||||
generate(android.languageMap)
|
||||
generate(android.languageMap, project)
|
||||
println("Strings generated!")
|
||||
}
|
||||
|
||||
private def generate(Map<String, String> sources) {
|
||||
private def generate(Map<String, String> sources, Project project) {
|
||||
if (sources == null || sources.isEmpty()) {
|
||||
throw new IOException("languageMap can't be null or empty")
|
||||
}
|
||||
|
|
@ -31,7 +31,7 @@ private def generate(Map<String, String> sources) {
|
|||
}
|
||||
}
|
||||
|
||||
def stringsFile = getFile(key, key == defaultLang)
|
||||
def stringsFile = getFile(key, key == defaultLang, project)
|
||||
stringsFile.write(sw.toString(), "UTF-8")
|
||||
}
|
||||
}
|
||||
|
|
@ -69,15 +69,15 @@ private static Map<String, Object> getJsonsMap(Map sources) {
|
|||
}
|
||||
}
|
||||
|
||||
private static File getFile(String key, boolean defaultLang) {
|
||||
private static File getFile(String key, boolean defaultLang, Project project) {
|
||||
if (defaultLang) {
|
||||
return new File("app/src/main/res/values/strings.xml")
|
||||
return project.file("src/main/res/values/strings.xml")
|
||||
} else {
|
||||
def directory = new File("app/src/main/res/values-$key")
|
||||
def directory = project.file("src/main/res/values-$key")
|
||||
if (!directory.exists()) {
|
||||
directory.mkdir()
|
||||
}
|
||||
return new File("app/src/main/res/values-$key/strings.xml")
|
||||
return project.file("src/main/res/values-$key/strings.xml")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,166 +0,0 @@
|
|||
buildscript {
|
||||
repositories {
|
||||
maven { url "https://plugins.gradle.org/m2" }
|
||||
}
|
||||
dependencies {
|
||||
classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.5.1"
|
||||
}
|
||||
}
|
||||
|
||||
def getServerProjectSources
|
||||
def getAndroidProjectSources
|
||||
|
||||
apply from: "$buildScriptsDir/gradle/commonStaticAnalysis.gradle"
|
||||
|
||||
gradle.projectsEvaluated {
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
options.compilerArgs <<
|
||||
"-Xlint:cast" <<
|
||||
"-Xlint:divzero" <<
|
||||
"-Xlint:empty" <<
|
||||
"-Xlint:deprecation" <<
|
||||
"-Xlint:finally" <<
|
||||
"-Xlint:overrides" <<
|
||||
"-Xlint:path" <<
|
||||
"-Werror"
|
||||
}
|
||||
|
||||
def excludes = rootProject.extensions.findByName("staticAnalysisExcludes")
|
||||
|
||||
def androidSources = getAndroidProjectSources(excludes)
|
||||
def androidStaticAnalysisTasks = getStaticAnalysisTaskNames(true, androidSources, null)
|
||||
def androidIdeaFormatTask = getIdeaFormatTask(true, androidSources)
|
||||
|
||||
task staticAnalysisWithFormatting {
|
||||
androidStaticAnalysisTasks.each { task ->
|
||||
tasks.findByName(task)?.mustRunAfter(androidIdeaFormatTask)
|
||||
}
|
||||
dependsOn androidIdeaFormatTask
|
||||
dependsOn androidStaticAnalysisTasks
|
||||
doFirst {
|
||||
generateReport(true)
|
||||
}
|
||||
}
|
||||
|
||||
task staticAnalysis {
|
||||
dependsOn androidStaticAnalysisTasks
|
||||
doFirst {
|
||||
generateReport(true)
|
||||
}
|
||||
}
|
||||
|
||||
def serverStaticAnalysisTasks = getStaticAnalysisTaskNames(false, getServerProjectSources(excludes), null)
|
||||
def serverIdeaFormatTask = getIdeaFormatTask(false, getServerProjectSources(excludes))
|
||||
|
||||
task serverStaticAnalysisWithFormatting {
|
||||
serverStaticAnalysisTasks.each { task ->
|
||||
tasks.findByName(task)?.mustRunAfter(serverIdeaFormatTask)
|
||||
}
|
||||
dependsOn serverIdeaFormatTask
|
||||
dependsOn serverStaticAnalysisTasks
|
||||
doFirst {
|
||||
generateReport(false)
|
||||
}
|
||||
}
|
||||
|
||||
task serverStaticAnalysis {
|
||||
dependsOn serverStaticAnalysisTasks
|
||||
doFirst {
|
||||
generateReport(false)
|
||||
}
|
||||
}
|
||||
|
||||
subprojects { subproject ->
|
||||
if (subproject.plugins.hasPlugin("com.android.application")) {
|
||||
subproject.android {
|
||||
lintOptions.abortOnError = false
|
||||
lintOptions.checkAllWarnings = true
|
||||
lintOptions.warningsAsErrors = false
|
||||
lintOptions.xmlReport = true
|
||||
lintOptions.xmlOutput = file "$rootProject.buildDir/reports/lint_report.xml"
|
||||
lintOptions.htmlReport = false
|
||||
lintOptions.lintConfig = file "$buildScriptsDir/lint/lint.xml"
|
||||
lintOptions.checkDependencies true
|
||||
lintOptions.disable 'MissingConstraints', 'VectorRaster'
|
||||
|
||||
applicationVariants.all { variant ->
|
||||
task("staticAnalysis${variant.name.capitalize()}") {
|
||||
dependsOn getStaticAnalysisTaskNames(true, androidSources, variant)
|
||||
doFirst { generateReport(true) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def regex = ~':detekt$'
|
||||
tasks.forEach { task ->
|
||||
if (!task.name.contains(":libs") && task.path =~ regex) {
|
||||
task.exclude '**/test/**'
|
||||
task.exclude 'resources/'
|
||||
task.exclude 'build/'
|
||||
task.exclude 'tmp/'
|
||||
|
||||
task.jvmTarget = "1.8"
|
||||
}
|
||||
}
|
||||
|
||||
detekt {
|
||||
config = files("$buildScriptsDir/kotlin/detekt-config.yml")
|
||||
|
||||
reports {
|
||||
txt.enabled = false
|
||||
html.enabled = false
|
||||
xml {
|
||||
enabled = true
|
||||
destination = file("${rootProject.buildDir}/reports/kotlin-detekt-${subproject.name}.xml")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getServerProjectSources = { excludes ->
|
||||
def sources = new ArrayList<String>()
|
||||
def sourcesDirectory = new File(project.projectDir.path, 'src')
|
||||
|
||||
for (def sourceFlavorDirectory : sourcesDirectory.listFiles()) {
|
||||
def javaSourceDirectory = new File(sourceFlavorDirectory.path, 'java')
|
||||
def kotlinSourceDirectory = new File(sourceFlavorDirectory.path, 'kotlin')
|
||||
|
||||
if (javaSourceDirectory.exists() && javaSourceDirectory.isDirectory()) {
|
||||
sources.add(javaSourceDirectory.absolutePath)
|
||||
}
|
||||
if (kotlinSourceDirectory.exists() && kotlinSourceDirectory.isDirectory()) {
|
||||
sources.add(kotlinSourceDirectory.absolutePath)
|
||||
}
|
||||
}
|
||||
return sources
|
||||
}
|
||||
|
||||
getAndroidProjectSources = { excludes ->
|
||||
def sources = new ArrayList<String>()
|
||||
for (def project : rootProject.subprojects) {
|
||||
if (!project.subprojects.isEmpty() || (excludes != null && excludes.contains(project.path))) {
|
||||
continue
|
||||
}
|
||||
|
||||
def sourcesDirectory = new File(project.projectDir.path, 'src')
|
||||
if (!sourcesDirectory.exists() || !sourcesDirectory.isDirectory()) {
|
||||
continue
|
||||
}
|
||||
|
||||
for (def sourceFlavorDirectory : sourcesDirectory.listFiles()) {
|
||||
def javaSourceDirectory = new File(sourceFlavorDirectory.path, 'java')
|
||||
def kotlinSourceDirectory = new File(sourceFlavorDirectory.path, 'kotlin')
|
||||
|
||||
if (javaSourceDirectory.exists() && javaSourceDirectory.isDirectory()) {
|
||||
sources.add(javaSourceDirectory.absolutePath)
|
||||
}
|
||||
if (kotlinSourceDirectory.exists() && kotlinSourceDirectory.isDirectory()) {
|
||||
sources.add(kotlinSourceDirectory.absolutePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
return sources
|
||||
}
|
||||
272
lint/lint.xml
272
lint/lint.xml
|
|
@ -1,272 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<lint>
|
||||
|
||||
<issue id="InvalidPackage" severity="error">
|
||||
<ignore regexp="Invalid package reference in library.*not included in Android.*java.*"/>
|
||||
</issue>
|
||||
<issue id="GradleCompatible" severity="error">
|
||||
<ignore regexp="All com.android.support libraries must use the exact same version specification (mixing versions can lead to runtime crashes). Found versions *. Examples include *"/>
|
||||
</issue>
|
||||
<!-- todo: lint bug? -->
|
||||
<issue id="MissingPermission" severity="ignore"/>
|
||||
<!-- todo: lint bug? -->
|
||||
<issue id="MissingSuperCall" severity="ignore"/>
|
||||
|
||||
<!--All activities should have locked orientation-->
|
||||
<issue id="LockedOrientationActivity" severity="ignore"/>
|
||||
|
||||
<issue id="AllowAllHostnameVerifier" severity="error"/>
|
||||
<issue id="InvalidUsesTagAttribute" severity="error"/>
|
||||
<issue id="MissingIntentFilterForMediaSearch" severity="error"/>
|
||||
<issue id="MissingMediaBrowserServiceIntentFilter" severity="error"/>
|
||||
<issue id="MissingOnPlayFromSearch" severity="error"/>
|
||||
<issue id="ShiftFlags" severity="error"/>
|
||||
<issue id="LocalSuppress" severity="error"/>
|
||||
<issue id="SwitchIntDef" severity="error"/>
|
||||
<issue id="UniqueConstants" severity="error"/>
|
||||
<issue id="InlinedApi" severity="error"/>
|
||||
<issue id="Override" severity="error"/>
|
||||
<issue id="UnusedAttribute" severity="warning"/>
|
||||
<issue id="AppCompatResource" severity="error"/>
|
||||
<issue id="BadHostnameVerifier" severity="error"/>
|
||||
<issue id="EnforceUTF8" severity="error"/>
|
||||
<issue id="ByteOrderMark" severity="error"/>
|
||||
<issue id="StopShip" severity="error"/>
|
||||
<issue id="MissingPrefix" severity="error"/>
|
||||
<issue id="MangledCRLF" severity="error"/>
|
||||
<issue id="DuplicateIds" severity="error"/>
|
||||
<issue id="DuplicateDefinition" severity="error"/>
|
||||
<issue id="ReferenceType" severity="error"/>
|
||||
<issue id="UnsafeDynamicallyLoadedCode" severity="error"/>
|
||||
<issue id="UnsafeNativeCodeLocation" severity="error"/>
|
||||
<issue id="FullBackupContent" severity="error"/>
|
||||
<issue id="ValidFragment" severity="error"/>
|
||||
<issue id="GradleCompatible" severity="error"/>
|
||||
<issue id="GradlePluginVersion" severity="error"/>
|
||||
<issue id="GradleGetter" severity="error"/>
|
||||
<issue id="GradleIdeError" severity="error"/>
|
||||
<issue id="NotInterpolated" severity="error"/>
|
||||
<issue id="StringShouldBeInt" severity="error"/>
|
||||
<issue id="AccidentalOctal" severity="error"/>
|
||||
<issue id="GridLayout" severity="error"/>
|
||||
<issue id="HardcodedDebugMode" severity="error"/>
|
||||
<issue id="IconExpectedSize" severity="error"/>
|
||||
<issue id="IncludeLayoutParam" severity="error"/>
|
||||
<issue id="TrustAllX509TrustManager" severity="warning"/>
|
||||
<issue id="DefaultLocale" severity="error"/>
|
||||
<issue id="InvalidResourceFolder" severity="error"/>
|
||||
<issue id="LongLogTag" severity="error"/>
|
||||
<issue id="LogTagMismatch" severity="error"/>
|
||||
<issue id="DuplicateActivity" severity="error"/>
|
||||
<issue id="MockLocation" severity="error"/>
|
||||
<issue id="MultipleUsesSdk" severity="error"/>
|
||||
<issue id="UniquePermission" severity="error"/>
|
||||
<issue id="WrongManifestParent" severity="error"/>
|
||||
<issue id="ManifestResource" severity="error"/>
|
||||
<issue id="ManifestTypo" severity="error"/>
|
||||
<issue id="Instantiatable" severity="error"/>
|
||||
<issue id="LibraryCustomView" severity="error"/>
|
||||
<issue id="ResAuto" severity="error"/>
|
||||
<issue id="NamespaceTypo" severity="error"/>
|
||||
<issue id="UnusedNamespace" severity="error"/>
|
||||
<issue id="NfcTechWhitespace" severity="error"/>
|
||||
<issue id="OnClick" severity="error"/>
|
||||
<issue id="DalvikOverride" severity="error"/>
|
||||
<issue id="OverrideAbstract" severity="error"/>
|
||||
<issue id="ParcelCreator" severity="error"/>
|
||||
<issue id="PackagedPrivateKey" severity="error"/>
|
||||
<issue id="Proguard" severity="error"/>
|
||||
<issue id="PropertyEscape" severity="error"/>
|
||||
<issue id="ParcelClassLoader" severity="error"/>
|
||||
<issue id="RecyclerView" severity="error"/>
|
||||
<issue id="RequiredSize" severity="error"/>
|
||||
<issue id="AaptCrash" severity="error"/>
|
||||
<issue id="ResourceCycle" severity="error"/>
|
||||
<issue id="ResourceName" severity="error"/>
|
||||
<issue id="ValidRestrictions" severity="error"/>
|
||||
<issue id="RtlCompat" severity="error"/>
|
||||
<issue id="ScrollViewSize" severity="error"/>
|
||||
<issue id="SecureRandom" severity="error"/>
|
||||
<issue id="SetWorldReadable" severity="error"/>
|
||||
<issue id="SetWorldWritable" severity="error"/>
|
||||
<issue id="ServiceCast" severity="error"/>
|
||||
<issue id="SSLCertificateSocketFactoryCreateSocket" severity="error"/>
|
||||
<issue id="SSLCertificateSocketFactoryGetInsecure" severity="error"/>
|
||||
<issue id="StringFormatMatches" severity="error"/>
|
||||
<issue id="StringFormatInvalid" severity="error"/>
|
||||
<issue id="UseCheckPermission" severity="error"/>
|
||||
<issue id="CheckResult" severity="warning"/>
|
||||
<issue id="ResourceAsColor" severity="error"/>
|
||||
<issue id="Range" severity="error"/>
|
||||
<issue id="ResourceType" severity="warning"/>
|
||||
<issue id="WrongThread" severity="error"/>
|
||||
<issue id="WrongConstant" severity="error"/>
|
||||
<issue id="ProtectedPermissions" severity="error"/>
|
||||
<issue id="MenuTitle" severity="error"/>
|
||||
<issue id="ExtraTranslation" severity="error"/>
|
||||
<issue id="MissingLeanbackLauncher" severity="error"/>
|
||||
<issue id="MissingLeanbackSupport" severity="error"/>
|
||||
<issue id="PermissionImpliesUnsupportedHardware" severity="error"/>
|
||||
<issue id="UnsupportedTvHardware" severity="error"/>
|
||||
<issue id="MissingTvBanner" severity="error"/>
|
||||
<issue id="TypographyOther" severity="error"/>
|
||||
<issue id="TypographyQuotes" severity="warning"/>
|
||||
<issue id="UnsafeProtectedBroadcastReceiver" severity="error"/>
|
||||
<issue id="UnprotectedSMSBroadcastReceiver" severity="error"/>
|
||||
<issue id="VectorRaster" severity="error"/>
|
||||
<issue id="ViewTag" severity="error"/>
|
||||
<issue id="WrongViewCast" severity="error"/>
|
||||
<issue id="Wakelock" severity="error"/>
|
||||
<issue id="WrongCall" severity="error"/>
|
||||
<issue id="WrongCase" severity="error"/>
|
||||
<issue id="InvalidId" severity="error"/>
|
||||
<issue id="NotSibling" severity="error"/>
|
||||
<issue id="UnknownIdInLayout" severity="error"/>
|
||||
<issue id="WrongFolder" severity="error"/>
|
||||
<issue id="AdapterViewChildren" severity="error"/>
|
||||
<issue id="SetJavaScriptEnabled" severity="warning"/>
|
||||
<issue id="AddJavascriptInterface" severity="warning"/>
|
||||
<issue id="AllowBackup" severity="error"/>
|
||||
<issue id="AlwaysShowAction" severity="error"/>
|
||||
<issue id="AppCompatMethod" severity="error"/>
|
||||
<issue id="Assert" severity="error"/>
|
||||
<issue id="CommitPrefEdits" severity="error"/>
|
||||
<issue id="CommitTransaction" severity="error"/>
|
||||
<issue id="CustomViewStyleable" severity="error"/>
|
||||
<issue id="CutPasteId" severity="error"/>
|
||||
<issue id="Deprecated" severity="error"/>
|
||||
<issue id="DeviceAdmin" severity="error"/>
|
||||
<issue id="DisableBaselineAlignment" severity="error"/>
|
||||
<issue id="DrawAllocation" severity="warning"/>
|
||||
<issue id="DuplicateIncludedIds" severity="error"/>
|
||||
<issue id="DuplicateUsesFeature" severity="error"/>
|
||||
<issue id="ExportedContentProvider" severity="error"/>
|
||||
<issue id="ExportedReceiver" severity="error"/>
|
||||
<issue id="ExportedService" severity="error"/>
|
||||
<issue id="ExtraText" severity="error"/>
|
||||
<issue id="GetInstance" severity="error"/>
|
||||
<issue id="GifUsage" severity="warning"/>
|
||||
<issue id="GradleDependency" severity="warning"/>
|
||||
<issue id="GradleDeprecated" severity="error"/>
|
||||
<issue id="GradleDynamicVersion" severity="error"/>
|
||||
<issue id="GradleOverrides" severity="error"/>
|
||||
<issue id="GradlePath" severity="warning"/>
|
||||
<issue id="GrantAllUris" severity="error"/>
|
||||
<issue id="HandlerLeak" severity="error"/>
|
||||
<issue id="HardcodedText" severity="error"/>
|
||||
<issue id="IconColors" severity="warning"/>
|
||||
<issue id="IconDensities" severity="warning"/>
|
||||
<issue id="IconDipSize" severity="error"/>
|
||||
<issue id="IconDuplicates" severity="error"/>
|
||||
<issue id="IconDuplicatesConfig" severity="error"/>
|
||||
<issue id="IconExtension" severity="error"/>
|
||||
<issue id="IconLocation" severity="error"/>
|
||||
<issue id="IconMixedNinePatch" severity="error"/>
|
||||
<issue id="IconNoDpi" severity="error"/>
|
||||
<issue id="IconXmlAndPng" severity="error"/>
|
||||
<issue id="IllegalResourceRef" severity="error"/>
|
||||
<issue id="InOrMmUsage" severity="error"/>
|
||||
<issue id="InconsistentArrays" severity="error"/>
|
||||
<issue id="InefficientWeight" severity="warning"/>
|
||||
<issue id="InflateParams" severity="warning"/>
|
||||
<issue id="InnerclassSeparator" severity="error"/>
|
||||
<issue id="LocaleFolder" severity="error"/>
|
||||
<issue id="LogConditional" severity="error"/>
|
||||
<issue id="ManifestOrder" severity="error"/>
|
||||
<issue id="MipmapIcons" severity="error"/>
|
||||
<issue id="MissingApplicationIcon" severity="error"/>
|
||||
<issue id="MissingId" severity="error"/>
|
||||
<issue id="MissingVersion" severity="error"/>
|
||||
<issue id="NestedWeights" severity="warning"/>
|
||||
<issue id="NewerVersionAvailable" severity="warning"/>
|
||||
<issue id="ObsoleteLayoutParam" severity="error"/>
|
||||
<issue id="OldTargetApi" severity="error"/>
|
||||
<issue id="PackageManagerGetSignatures" severity="error"/>
|
||||
<issue id="PrivateResource" severity="error"/>
|
||||
<issue id="ProguardSplit" severity="error"/>
|
||||
<issue id="PxUsage" severity="error"/>
|
||||
<issue id="Recycle" severity="error"/>
|
||||
<issue id="Registered" severity="error"/>
|
||||
<issue id="RtlEnabled" severity="error"/>
|
||||
<issue id="SQLiteString" severity="error"/>
|
||||
<issue id="ScrollViewCount" severity="error"/>
|
||||
<issue id="ScrollViewSize" severity="error"/>
|
||||
<issue id="SdCardPath" severity="error"/>
|
||||
<issue id="ShortAlarm" severity="warning"/>
|
||||
<issue id="ShowToast" severity="error"/>
|
||||
<issue id="SignatureOrSystemPermissions" severity="error"/>
|
||||
<issue id="SimpleDateFormat" severity="error"/>
|
||||
<issue id="SpUsage" severity="error"/>
|
||||
<issue id="StateListReachable" severity="error"/>
|
||||
<issue id="SuspiciousImport" severity="error"/>
|
||||
<issue id="TextFields" severity="error"/>
|
||||
<issue id="TextViewEdits" severity="error"/>
|
||||
<issue id="TooDeepLayout" severity="warning"/>
|
||||
<issue id="TooManyViews" severity="warning"/>
|
||||
<issue id="TypographyDashes" severity="warning"/>
|
||||
<issue id="UnknownIdInLayout" severity="error"/>
|
||||
<issue id="UnlocalizedSms" severity="error"/>
|
||||
<issue id="UnusedIds" severity="error"/>
|
||||
<issue id="UseAlpha2" severity="error"/>
|
||||
<issue id="UseSparseArrays" severity="warning"/>
|
||||
<issue id="UseValueOf" severity="error"/>
|
||||
<issue id="UsesMinSdkAttributes" severity="error"/>
|
||||
<issue id="UsingHttp" severity="warning"/>
|
||||
<issue id="WorldReadableFiles" severity="warning"/>
|
||||
<issue id="WorldWriteableFiles" severity="warning"/>
|
||||
<issue id="WrongRegion" severity="warning"/>
|
||||
|
||||
<!-- DISABLE RULES BELOW -->
|
||||
<issue id="GoogleAppIndexingApiWarning" severity="ignore"/>
|
||||
<issue id="GoogleAppIndexingWarning" severity="ignore"/>
|
||||
<issue id="AppLinksAutoVerifyError" severity="ignore"/>
|
||||
<issue id="AppLinksAutoVerifyWarning" severity="ignore"/>
|
||||
<issue id="ClickableViewAccessibility" severity="ignore"/>
|
||||
<issue id="SetTextI18n" severity="ignore"/>
|
||||
<issue id="EasterEgg" severity="ignore"/>
|
||||
<issue id="BackButton" severity="ignore"/>
|
||||
<issue id="FieldGetter" severity="ignore"/>
|
||||
<issue id="Orientation" severity="ignore"/>
|
||||
<issue id="Suspicious0dp" severity="ignore"/>
|
||||
<issue id="NegativeMargin" severity="ignore"/>
|
||||
<issue id="MissingQuantity" severity="ignore"/>
|
||||
<issue id="ImpliedQuantity" severity="ignore"/>
|
||||
<issue id="TrulyRandom" severity="ignore"/>
|
||||
<issue id="SelectableText" severity="ignore"/>
|
||||
<issue id="UnusedIds" severity="ignore"/>
|
||||
<issue id="ButtonCase" severity="ignore"/>
|
||||
<issue id="ButtonOrder" severity="ignore"/>
|
||||
<issue id="ButtonStyle" severity="ignore"/>
|
||||
<issue id="ContentDescription" severity="ignore"/>
|
||||
<issue id="ExportedPreferenceActivity" severity="ignore"/>
|
||||
<!-- remove when facebook will update support library in sdk -->
|
||||
<issue id="GradleCompatible" severity="ignore"/>
|
||||
<issue id="IconLauncherShape" severity="ignore"/>
|
||||
<issue id="IconMissingDensityFolder" severity="ignore"/>
|
||||
<issue id="InconsistentLayout" severity="ignore"/>
|
||||
<issue id="LabelFor" severity="ignore"/>
|
||||
<issue id="MissingTranslation" severity="ignore"/>
|
||||
<issue id="NestedScrolling" severity="ignore"/>
|
||||
<issue id="MergeRootFrame" severity="ignore"/>
|
||||
<issue id="NewApi" severity="ignore"/>
|
||||
<issue id="Overdraw" severity="ignore"/>
|
||||
<issue id="PluralsCandidate" severity="ignore"/>
|
||||
<issue id="RelativeOverlap" severity="ignore"/>
|
||||
<issue id="RtlHardcoded" severity="ignore"/>
|
||||
<issue id="RtlSymmetry" severity="ignore"/>
|
||||
<issue id="SmallSp" severity="ignore"/>
|
||||
<issue id="StringFormatCount" severity="ignore"/>
|
||||
<issue id="TypographyFractions" severity="ignore"/>
|
||||
<issue id="Typos" severity="ignore"/>
|
||||
<issue id="UnusedQuantity" severity="ignore"/>
|
||||
<issue id="UnusedResources" severity="ignore"/>
|
||||
<issue id="UseCompoundDrawables" severity="ignore"/>
|
||||
<issue id="UselessLeaf" severity="ignore"/>
|
||||
<issue id="UselessParent" severity="ignore"/>
|
||||
<issue id="ViewConstructor" severity="ignore"/>
|
||||
<issue id="ViewHolder" severity="ignore"/>
|
||||
<issue id="WebViewLayout" severity="ignore"/>
|
||||
<issue id="TypographyEllipsis" severity="ignore"/>
|
||||
<issue id="PermissionImpliesUnsupportedChromeOsHardware" severity="ignore"/>
|
||||
|
||||
</lint>
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<ruleset name="All Java Rules"
|
||||
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
|
||||
<description>Every Java Rule in PMD</description>
|
||||
|
||||
<rule ref="rulesets/java/android.xml"/>
|
||||
<rule ref="rulesets/java/basic.xml">
|
||||
<exclude name="SimplifiedTernary"/>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/braces.xml"/>
|
||||
<rule ref="rulesets/java/clone.xml"/>
|
||||
<rule ref="rulesets/java/codesize.xml"/>
|
||||
<rule ref="rulesets/java/codesize.xml/TooManyMethods">
|
||||
<properties>
|
||||
<property name="maxmethods" value="20"/>
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/codesize.xml/CyclomaticComplexity">
|
||||
<properties>
|
||||
<property name="showClassesComplexity" value="false"/>
|
||||
<property name="violationSuppressXPath" value="./MethodDeclarator[@Image='hashCode' or @Image='equals']"/>
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/codesize.xml/StdCyclomaticComplexity">
|
||||
<properties>
|
||||
<property name="showClassesComplexity" value="false"/>
|
||||
<property name="violationSuppressXPath" value="./MethodDeclarator[@Image='hashCode' or @Image='equals']"/>
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/codesize.xml/ModifiedCyclomaticComplexity">
|
||||
<properties>
|
||||
<property name="showClassesComplexity" value="false"/>
|
||||
<property name="violationSuppressXPath" value="./MethodDeclarator[@Image='hashCode' or @Image='equals']"/>
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/codesize.xml/NPathComplexity">
|
||||
<properties>
|
||||
<property name="violationSuppressXPath" value="./MethodDeclarator[@Image='hashCode' or @Image='equals']"/>
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/comments.xml">
|
||||
<exclude name="CommentSize"/>
|
||||
<exclude name="CommentRequired"/>
|
||||
<exclude name="CommentDefaultAccessModifier"/>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/controversial.xml">
|
||||
<exclude name="AtLeastOneConstructor"/>
|
||||
<exclude name="OnlyOneReturn"/>
|
||||
<exclude name="UseConcurrentHashMap"/>
|
||||
<exclude name="NullAssignment"/>
|
||||
<exclude name="DataflowAnomalyAnalysis"/>
|
||||
<exclude name="AvoidFinalLocalVariable"/>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/controversial.xml/AvoidLiteralsInIfCondition">
|
||||
<properties>
|
||||
<property name="ignoreMagicNumbers" value="-1,0,1"/>
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/coupling.xml">
|
||||
<exclude name="LoosePackageCoupling"/>
|
||||
<exclude name="LawOfDemeter"/>
|
||||
<exclude name="LooseCoupling"/>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/coupling.xml/ExcessiveImports">
|
||||
<properties>
|
||||
<property name="minimum" value="50"/>
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/design.xml">
|
||||
<exclude name="GodClass"/>
|
||||
<exclude name="ConfusingTernary"/>
|
||||
<exclude name="ReturnEmptyArrayRatherThanNull"/>
|
||||
<exclude name="FieldDeclarationsShouldBeAtStartOfClass"/>
|
||||
<exclude name="EmptyMethodInAbstractClassShouldBeAbstract"/>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/empty.xml"/>
|
||||
<rule ref="rulesets/java/empty.xml/EmptyCatchBlock">
|
||||
<properties>
|
||||
<property name="allowCommentedBlocks" value="true"/>
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/finalizers.xml"/>
|
||||
<rule ref="rulesets/java/imports.xml"/>
|
||||
<rule ref="rulesets/java/j2ee.xml">
|
||||
<exclude name="DoNotUseThreads"/>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/javabeans.xml">
|
||||
<exclude name="BeanMembersShouldSerialize"/>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/junit.xml"/>
|
||||
<rule ref="rulesets/java/logging-jakarta-commons.xml">
|
||||
<exclude name="GuardLogStatement"/>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/logging-java.xml"/>
|
||||
<rule ref="rulesets/java/migrating.xml"/>
|
||||
<rule ref="rulesets/java/naming.xml">
|
||||
<exclude name="SuspiciousEqualsMethodName"/>
|
||||
<exclude name="AbstractNaming"/>
|
||||
<exclude name="ShortVariable"/>
|
||||
<exclude name="LongVariable"/>
|
||||
<exclude name="GenericsNaming"/>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/naming.xml/ShortClassName">
|
||||
<properties>
|
||||
<property name="minimum" value="4"/>
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/optimizations.xml">
|
||||
<exclude name="AvoidInstantiatingObjectsInLoops"/>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/strictexception.xml">
|
||||
<exclude name="AvoidCatchingGenericException"/>
|
||||
<exclude name="SignatureDeclareThrowsException"/>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/strings.xml"/>
|
||||
<rule ref="rulesets/java/sunsecure.xml">
|
||||
<exclude name="MethodReturnsInternalArray"/>
|
||||
<exclude name="ArrayIsStoredDirectly"/>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/typeresolution.xml">
|
||||
<exclude name="SignatureDeclareThrowsException"/>
|
||||
<exclude name="LooseCoupling"/>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/unnecessary.xml">
|
||||
<exclude name="UselessParentheses"/>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/unusedcode.xml"/>
|
||||
</ruleset>
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
-include rules/components.pro
|
||||
|
||||
-include rules/okhttp.pro
|
||||
-include rules/retrofit.pro
|
||||
-include rules/logansquare.pro
|
||||
|
|
@ -8,4 +7,3 @@
|
|||
-include rules/kaspersky.pro
|
||||
-include rules/appsflyer.pro
|
||||
-include rules/moshi.pro
|
||||
-include rules/androidx_security.pro
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
}
|
||||
|
||||
-keep @com.squareup.moshi.JsonQualifier interface *
|
||||
-keep @com.squareup.moshi.JsonQualifier class *
|
||||
|
||||
# Enum field names are used by the integrated EnumJsonAdapter.
|
||||
# values() is synthesized by the Kotlin compiler and is used by EnumJsonAdapter indirectly
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Description:
|
||||
# Creates archive with source code of multiple repositories.
|
||||
#
|
||||
# Parameters:
|
||||
# $1 - github repository name without suffix (project name).
|
||||
# $2, $3, ..., $n - repository suffixes (platforms).
|
||||
#
|
||||
# Optional environment variables:
|
||||
# GIT_BRANCH - branch to use. Default - master.
|
||||
#
|
||||
# Example of usage:
|
||||
# export_src.sh TestProject ios android backend
|
||||
# GIT_BRANCH="develop"; ./export_src.sh TestProject ios web
|
||||
#
|
||||
|
||||
if [ -z "${GIT_BRANCH}" ]; then
|
||||
GIT_BRANCH="master"
|
||||
fi
|
||||
|
||||
PROJECT_NAME=$1
|
||||
SRC_FOLDER_NAME="${PROJECT_NAME}-src-$(date +%F)"
|
||||
SRC_DIR="./${SRC_FOLDER_NAME}"
|
||||
|
||||
COMMAND_LINE_ARGUMENTS=$@
|
||||
|
||||
clone_platform() {
|
||||
PROJECT_NAME=$1
|
||||
PLATFORM=$2
|
||||
|
||||
git clone --recurse-submodules -j8 "git@github.com:TouchInstinct/${PROJECT_NAME}-${PLATFORM}.git" --branch "${GIT_BRANCH}"
|
||||
}
|
||||
|
||||
mkdir -p "${SRC_DIR}"
|
||||
cd "${SRC_DIR}"
|
||||
|
||||
for argument in ${COMMAND_LINE_ARGUMENTS}
|
||||
do
|
||||
if [ $argument != $PROJECT_NAME ]; then
|
||||
platform=${argument} # all arguments after project name treated as platforms
|
||||
clone_platform ${PROJECT_NAME} ${platform}
|
||||
fi
|
||||
done
|
||||
|
||||
find . -name ".git*" -print0 | xargs -0 rm -rf
|
||||
zip -r -q ${SRC_FOLDER_NAME}.zip .
|
||||
|
||||
open .
|
||||
|
|
@ -23,7 +23,7 @@ formatting:
|
|||
active: true
|
||||
|
||||
console-reports:
|
||||
active: true
|
||||
active: false
|
||||
exclude:
|
||||
# - 'ProjectStatisticsReport'
|
||||
# - 'ComplexityReport'
|
||||
|
|
@ -387,9 +387,6 @@ style:
|
|||
UnusedPrivateMember:
|
||||
active: true
|
||||
allowedNames: "(_|ignored|expected|serialVersionUID)"
|
||||
UseDataClass:
|
||||
active: true
|
||||
excludeAnnotatedClasses: ""
|
||||
UtilityClassWithPublicConstructor:
|
||||
active: false
|
||||
VarCouldBeVal:
|
||||
|
|
@ -0,0 +1,273 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<lint>
|
||||
|
||||
<issue id="InvalidPackage" severity="error">
|
||||
<ignore regexp="Invalid package reference in library.*not included in Android.*java.*" />
|
||||
</issue>
|
||||
<issue id="GradleCompatible" severity="error">
|
||||
<ignore
|
||||
regexp="All com.android.support libraries must use the exact same version specification (mixing versions can lead to runtime crashes). Found versions *. Examples include *" />
|
||||
</issue>
|
||||
<!-- todo: lint bug? -->
|
||||
<issue id="MissingPermission" severity="ignore" />
|
||||
<!-- todo: lint bug? -->
|
||||
<issue id="MissingSuperCall" severity="ignore" />
|
||||
|
||||
<!--All activities should have locked orientation-->
|
||||
<issue id="LockedOrientationActivity" severity="ignore" />
|
||||
|
||||
<issue id="AllowAllHostnameVerifier" severity="error" />
|
||||
<issue id="InvalidUsesTagAttribute" severity="error" />
|
||||
<issue id="MissingIntentFilterForMediaSearch" severity="error" />
|
||||
<issue id="MissingMediaBrowserServiceIntentFilter" severity="error" />
|
||||
<issue id="MissingOnPlayFromSearch" severity="error" />
|
||||
<issue id="ShiftFlags" severity="error" />
|
||||
<issue id="LocalSuppress" severity="error" />
|
||||
<issue id="SwitchIntDef" severity="error" />
|
||||
<issue id="UniqueConstants" severity="error" />
|
||||
<issue id="InlinedApi" severity="error" />
|
||||
<issue id="Override" severity="error" />
|
||||
<issue id="UnusedAttribute" severity="warning" />
|
||||
<issue id="AppCompatResource" severity="error" />
|
||||
<issue id="BadHostnameVerifier" severity="error" />
|
||||
<issue id="EnforceUTF8" severity="error" />
|
||||
<issue id="ByteOrderMark" severity="error" />
|
||||
<issue id="StopShip" severity="error" />
|
||||
<issue id="MissingPrefix" severity="error" />
|
||||
<issue id="MangledCRLF" severity="error" />
|
||||
<issue id="DuplicateIds" severity="error" />
|
||||
<issue id="DuplicateDefinition" severity="error" />
|
||||
<issue id="ReferenceType" severity="error" />
|
||||
<issue id="UnsafeDynamicallyLoadedCode" severity="error" />
|
||||
<issue id="UnsafeNativeCodeLocation" severity="error" />
|
||||
<issue id="FullBackupContent" severity="error" />
|
||||
<issue id="ValidFragment" severity="error" />
|
||||
<issue id="GradleCompatible" severity="error" />
|
||||
<issue id="GradlePluginVersion" severity="error" />
|
||||
<issue id="GradleGetter" severity="error" />
|
||||
<issue id="GradleIdeError" severity="error" />
|
||||
<issue id="NotInterpolated" severity="error" />
|
||||
<issue id="StringShouldBeInt" severity="error" />
|
||||
<issue id="AccidentalOctal" severity="error" />
|
||||
<issue id="GridLayout" severity="error" />
|
||||
<issue id="HardcodedDebugMode" severity="error" />
|
||||
<issue id="IconExpectedSize" severity="error" />
|
||||
<issue id="IncludeLayoutParam" severity="error" />
|
||||
<issue id="TrustAllX509TrustManager" severity="warning" />
|
||||
<issue id="DefaultLocale" severity="error" />
|
||||
<issue id="InvalidResourceFolder" severity="error" />
|
||||
<issue id="LongLogTag" severity="error" />
|
||||
<issue id="LogTagMismatch" severity="error" />
|
||||
<issue id="DuplicateActivity" severity="error" />
|
||||
<issue id="MockLocation" severity="error" />
|
||||
<issue id="MultipleUsesSdk" severity="error" />
|
||||
<issue id="UniquePermission" severity="error" />
|
||||
<issue id="WrongManifestParent" severity="error" />
|
||||
<issue id="ManifestResource" severity="error" />
|
||||
<issue id="ManifestTypo" severity="error" />
|
||||
<issue id="Instantiatable" severity="error" />
|
||||
<issue id="LibraryCustomView" severity="error" />
|
||||
<issue id="ResAuto" severity="error" />
|
||||
<issue id="NamespaceTypo" severity="error" />
|
||||
<issue id="UnusedNamespace" severity="error" />
|
||||
<issue id="NfcTechWhitespace" severity="error" />
|
||||
<issue id="OnClick" severity="error" />
|
||||
<issue id="DalvikOverride" severity="error" />
|
||||
<issue id="OverrideAbstract" severity="error" />
|
||||
<issue id="ParcelCreator" severity="error" />
|
||||
<issue id="PackagedPrivateKey" severity="error" />
|
||||
<issue id="Proguard" severity="error" />
|
||||
<issue id="PropertyEscape" severity="error" />
|
||||
<issue id="ParcelClassLoader" severity="error" />
|
||||
<issue id="RecyclerView" severity="error" />
|
||||
<issue id="RequiredSize" severity="error" />
|
||||
<issue id="AaptCrash" severity="error" />
|
||||
<issue id="ResourceCycle" severity="error" />
|
||||
<issue id="ResourceName" severity="error" />
|
||||
<issue id="ValidRestrictions" severity="error" />
|
||||
<issue id="RtlCompat" severity="error" />
|
||||
<issue id="ScrollViewSize" severity="error" />
|
||||
<issue id="SecureRandom" severity="error" />
|
||||
<issue id="SetWorldReadable" severity="error" />
|
||||
<issue id="SetWorldWritable" severity="error" />
|
||||
<issue id="ServiceCast" severity="error" />
|
||||
<issue id="SSLCertificateSocketFactoryCreateSocket" severity="error" />
|
||||
<issue id="SSLCertificateSocketFactoryGetInsecure" severity="error" />
|
||||
<issue id="StringFormatMatches" severity="error" />
|
||||
<issue id="StringFormatInvalid" severity="error" />
|
||||
<issue id="UseCheckPermission" severity="error" />
|
||||
<issue id="CheckResult" severity="warning" />
|
||||
<issue id="ResourceAsColor" severity="error" />
|
||||
<issue id="Range" severity="error" />
|
||||
<issue id="ResourceType" severity="warning" />
|
||||
<issue id="WrongThread" severity="error" />
|
||||
<issue id="WrongConstant" severity="error" />
|
||||
<issue id="ProtectedPermissions" severity="error" />
|
||||
<issue id="MenuTitle" severity="error" />
|
||||
<issue id="ExtraTranslation" severity="error" />
|
||||
<issue id="MissingLeanbackLauncher" severity="error" />
|
||||
<issue id="MissingLeanbackSupport" severity="error" />
|
||||
<issue id="PermissionImpliesUnsupportedHardware" severity="error" />
|
||||
<issue id="UnsupportedTvHardware" severity="error" />
|
||||
<issue id="MissingTvBanner" severity="error" />
|
||||
<issue id="TypographyOther" severity="error" />
|
||||
<issue id="TypographyQuotes" severity="warning" />
|
||||
<issue id="UnsafeProtectedBroadcastReceiver" severity="error" />
|
||||
<issue id="UnprotectedSMSBroadcastReceiver" severity="error" />
|
||||
<issue id="VectorRaster" severity="error" />
|
||||
<issue id="ViewTag" severity="error" />
|
||||
<issue id="WrongViewCast" severity="error" />
|
||||
<issue id="Wakelock" severity="error" />
|
||||
<issue id="WrongCall" severity="error" />
|
||||
<issue id="WrongCase" severity="error" />
|
||||
<issue id="InvalidId" severity="error" />
|
||||
<issue id="NotSibling" severity="error" />
|
||||
<issue id="UnknownIdInLayout" severity="error" />
|
||||
<issue id="WrongFolder" severity="error" />
|
||||
<issue id="AdapterViewChildren" severity="error" />
|
||||
<issue id="SetJavaScriptEnabled" severity="warning" />
|
||||
<issue id="AddJavascriptInterface" severity="warning" />
|
||||
<issue id="AllowBackup" severity="error" />
|
||||
<issue id="AlwaysShowAction" severity="error" />
|
||||
<issue id="AppCompatMethod" severity="error" />
|
||||
<issue id="Assert" severity="error" />
|
||||
<issue id="CommitPrefEdits" severity="error" />
|
||||
<issue id="CommitTransaction" severity="error" />
|
||||
<issue id="CustomViewStyleable" severity="error" />
|
||||
<issue id="CutPasteId" severity="error" />
|
||||
<issue id="Deprecated" severity="error" />
|
||||
<issue id="DeviceAdmin" severity="error" />
|
||||
<issue id="DisableBaselineAlignment" severity="error" />
|
||||
<issue id="DrawAllocation" severity="warning" />
|
||||
<issue id="DuplicateIncludedIds" severity="error" />
|
||||
<issue id="DuplicateUsesFeature" severity="error" />
|
||||
<issue id="ExportedContentProvider" severity="error" />
|
||||
<issue id="ExportedReceiver" severity="error" />
|
||||
<issue id="ExportedService" severity="error" />
|
||||
<issue id="ExtraText" severity="error" />
|
||||
<issue id="GetInstance" severity="error" />
|
||||
<issue id="GifUsage" severity="warning" />
|
||||
<issue id="GradleDependency" severity="warning" />
|
||||
<issue id="GradleDeprecated" severity="error" />
|
||||
<issue id="GradleDynamicVersion" severity="error" />
|
||||
<issue id="GradleOverrides" severity="error" />
|
||||
<issue id="GradlePath" severity="warning" />
|
||||
<issue id="GrantAllUris" severity="error" />
|
||||
<issue id="HandlerLeak" severity="error" />
|
||||
<issue id="HardcodedText" severity="error" />
|
||||
<issue id="IconColors" severity="warning" />
|
||||
<issue id="IconDensities" severity="warning" />
|
||||
<issue id="IconDipSize" severity="error" />
|
||||
<issue id="IconDuplicates" severity="error" />
|
||||
<issue id="IconDuplicatesConfig" severity="error" />
|
||||
<issue id="IconExtension" severity="error" />
|
||||
<issue id="IconLocation" severity="error" />
|
||||
<issue id="IconMixedNinePatch" severity="error" />
|
||||
<issue id="IconNoDpi" severity="error" />
|
||||
<issue id="IconXmlAndPng" severity="error" />
|
||||
<issue id="IllegalResourceRef" severity="error" />
|
||||
<issue id="InOrMmUsage" severity="error" />
|
||||
<issue id="InconsistentArrays" severity="error" />
|
||||
<issue id="InefficientWeight" severity="warning" />
|
||||
<issue id="InflateParams" severity="warning" />
|
||||
<issue id="InnerclassSeparator" severity="error" />
|
||||
<issue id="LocaleFolder" severity="error" />
|
||||
<issue id="LogConditional" severity="error" />
|
||||
<issue id="ManifestOrder" severity="error" />
|
||||
<issue id="MipmapIcons" severity="error" />
|
||||
<issue id="MissingApplicationIcon" severity="error" />
|
||||
<issue id="MissingId" severity="error" />
|
||||
<issue id="MissingVersion" severity="error" />
|
||||
<issue id="NestedWeights" severity="warning" />
|
||||
<issue id="NewerVersionAvailable" severity="warning" />
|
||||
<issue id="ObsoleteLayoutParam" severity="error" />
|
||||
<issue id="OldTargetApi" severity="error" />
|
||||
<issue id="PackageManagerGetSignatures" severity="error" />
|
||||
<issue id="PrivateResource" severity="error" />
|
||||
<issue id="ProguardSplit" severity="error" />
|
||||
<issue id="PxUsage" severity="error" />
|
||||
<issue id="Recycle" severity="error" />
|
||||
<issue id="Registered" severity="error" />
|
||||
<issue id="RtlEnabled" severity="error" />
|
||||
<issue id="SQLiteString" severity="error" />
|
||||
<issue id="ScrollViewCount" severity="error" />
|
||||
<issue id="ScrollViewSize" severity="error" />
|
||||
<issue id="SdCardPath" severity="error" />
|
||||
<issue id="ShortAlarm" severity="warning" />
|
||||
<issue id="ShowToast" severity="error" />
|
||||
<issue id="SignatureOrSystemPermissions" severity="error" />
|
||||
<issue id="SimpleDateFormat" severity="error" />
|
||||
<issue id="SpUsage" severity="error" />
|
||||
<issue id="StateListReachable" severity="error" />
|
||||
<issue id="SuspiciousImport" severity="error" />
|
||||
<issue id="TextFields" severity="error" />
|
||||
<issue id="TextViewEdits" severity="error" />
|
||||
<issue id="TooDeepLayout" severity="warning" />
|
||||
<issue id="TooManyViews" severity="warning" />
|
||||
<issue id="TypographyDashes" severity="warning" />
|
||||
<issue id="UnknownIdInLayout" severity="error" />
|
||||
<issue id="UnlocalizedSms" severity="error" />
|
||||
<issue id="UnusedIds" severity="error" />
|
||||
<issue id="UseAlpha2" severity="error" />
|
||||
<issue id="UseSparseArrays" severity="warning" />
|
||||
<issue id="UseValueOf" severity="error" />
|
||||
<issue id="UsesMinSdkAttributes" severity="error" />
|
||||
<issue id="UsingHttp" severity="warning" />
|
||||
<issue id="WorldReadableFiles" severity="warning" />
|
||||
<issue id="WorldWriteableFiles" severity="warning" />
|
||||
<issue id="WrongRegion" severity="warning" />
|
||||
|
||||
<!-- DISABLE RULES BELOW -->
|
||||
<issue id="GoogleAppIndexingApiWarning" severity="ignore" />
|
||||
<issue id="GoogleAppIndexingWarning" severity="ignore" />
|
||||
<issue id="AppLinksAutoVerifyError" severity="ignore" />
|
||||
<issue id="AppLinksAutoVerifyWarning" severity="ignore" />
|
||||
<issue id="ClickableViewAccessibility" severity="ignore" />
|
||||
<issue id="SetTextI18n" severity="ignore" />
|
||||
<issue id="EasterEgg" severity="ignore" />
|
||||
<issue id="BackButton" severity="ignore" />
|
||||
<issue id="FieldGetter" severity="ignore" />
|
||||
<issue id="Orientation" severity="ignore" />
|
||||
<issue id="Suspicious0dp" severity="ignore" />
|
||||
<issue id="NegativeMargin" severity="ignore" />
|
||||
<issue id="MissingQuantity" severity="ignore" />
|
||||
<issue id="ImpliedQuantity" severity="ignore" />
|
||||
<issue id="TrulyRandom" severity="ignore" />
|
||||
<issue id="SelectableText" severity="ignore" />
|
||||
<issue id="UnusedIds" severity="ignore" />
|
||||
<issue id="ButtonCase" severity="ignore" />
|
||||
<issue id="ButtonOrder" severity="ignore" />
|
||||
<issue id="ButtonStyle" severity="ignore" />
|
||||
<issue id="ContentDescription" severity="ignore" />
|
||||
<issue id="ExportedPreferenceActivity" severity="ignore" />
|
||||
<!-- remove when facebook will update support library in sdk -->
|
||||
<issue id="GradleCompatible" severity="ignore" />
|
||||
<issue id="IconLauncherShape" severity="ignore" />
|
||||
<issue id="IconMissingDensityFolder" severity="ignore" />
|
||||
<issue id="InconsistentLayout" severity="ignore" />
|
||||
<issue id="LabelFor" severity="ignore" />
|
||||
<issue id="MissingTranslation" severity="ignore" />
|
||||
<issue id="NestedScrolling" severity="ignore" />
|
||||
<issue id="MergeRootFrame" severity="ignore" />
|
||||
<issue id="NewApi" severity="ignore" />
|
||||
<issue id="Overdraw" severity="ignore" />
|
||||
<issue id="PluralsCandidate" severity="ignore" />
|
||||
<issue id="RelativeOverlap" severity="ignore" />
|
||||
<issue id="RtlHardcoded" severity="ignore" />
|
||||
<issue id="RtlSymmetry" severity="ignore" />
|
||||
<issue id="SmallSp" severity="ignore" />
|
||||
<issue id="StringFormatCount" severity="ignore" />
|
||||
<issue id="TypographyFractions" severity="ignore" />
|
||||
<issue id="Typos" severity="ignore" />
|
||||
<issue id="UnusedQuantity" severity="ignore" />
|
||||
<issue id="UnusedResources" severity="ignore" />
|
||||
<issue id="UseCompoundDrawables" severity="ignore" />
|
||||
<issue id="UselessLeaf" severity="ignore" />
|
||||
<issue id="UselessParent" severity="ignore" />
|
||||
<issue id="ViewConstructor" severity="ignore" />
|
||||
<issue id="ViewHolder" severity="ignore" />
|
||||
<issue id="WebViewLayout" severity="ignore" />
|
||||
<issue id="TypographyEllipsis" severity="ignore" />
|
||||
<issue id="PermissionImpliesUnsupportedChromeOsHardware" severity="ignore" />
|
||||
|
||||
</lint>
|
||||
|
|
@ -32,6 +32,8 @@ opt_in_rules:
|
|||
- fatal_error_message
|
||||
- extension_access_modifier
|
||||
- explicit_init
|
||||
- prefer_zero_over_explicit_init
|
||||
- fallthrough
|
||||
|
||||
# style
|
||||
|
||||
|
|
@ -64,6 +66,7 @@ opt_in_rules:
|
|||
- identical_operands
|
||||
- overridden_super_call
|
||||
- unowned_variable_capture
|
||||
- comment_spacing
|
||||
|
||||
# metrics
|
||||
|
||||
|
|
@ -73,7 +76,8 @@ excluded:
|
|||
- Carthage
|
||||
- Pods
|
||||
- Generated
|
||||
- Localization
|
||||
- "**/Generated"
|
||||
- "**/Resources"
|
||||
|
||||
line_length:
|
||||
warning: 128
|
||||
|
|
@ -111,6 +115,8 @@ identifier_name:
|
|||
|
||||
warning_threshold: 1
|
||||
|
||||
allow_zero_lintable_files: true
|
||||
|
||||
custom_rules:
|
||||
|
||||
# General
|
||||
|
|
@ -186,26 +192,12 @@ custom_rules:
|
|||
regex: '(?!\n)[^ \n]+ {2,}.+'
|
||||
message: "Remove excess empty spaces"
|
||||
severity: warning
|
||||
match_kinds:
|
||||
- argument
|
||||
- attribute.builtin
|
||||
- attribute.id
|
||||
- buildconfig.id
|
||||
- buildconfig.keyword
|
||||
- identifier
|
||||
- keyword
|
||||
- number
|
||||
- objectliteral
|
||||
- parameter
|
||||
- placeholder
|
||||
# - string # all except string literals
|
||||
# - comment # and comments
|
||||
# - comment.mark
|
||||
# - comment.url
|
||||
# - doccomment
|
||||
# - doccomment.field
|
||||
- string_interpolation_anchor
|
||||
- typeidentifier
|
||||
excluded_match_kinds:
|
||||
- comment
|
||||
- comment.mark
|
||||
- comment.url
|
||||
- doccomment
|
||||
- doccomment.field
|
||||
|
||||
getter_setter_style:
|
||||
name: "Wrong getter/setter code style"
|
||||
|
|
@ -213,43 +205,67 @@ custom_rules:
|
|||
match_kinds:
|
||||
- keyword
|
||||
message: "Make a new line break when use getter or setter"
|
||||
severity: error
|
||||
severity: warning
|
||||
|
||||
redundant_boolean_condition:
|
||||
name: "Redundant Boolean Condition"
|
||||
regex: "(== true)|(== false)|(!= true)|(!= false)"
|
||||
message: "Comparing a boolean to true is redundant (use `?? false` for optionals), and `!`-syntax is preferred over comparing to false."
|
||||
severity: error
|
||||
severity: warning
|
||||
excluded_match_kinds:
|
||||
- comment
|
||||
- comment.mark
|
||||
- comment.url
|
||||
- doccomment
|
||||
- doccomment.field
|
||||
|
||||
redundant_ternary_operator:
|
||||
name: "Redundant Ternary Operator"
|
||||
regex: "(\\? true \\: false)|(\\? false \\: true)"
|
||||
message: "Returning a boolean as true is redundant, and `!`-syntax is preferred over returning as false."
|
||||
severity: error
|
||||
severity: warning
|
||||
|
||||
single_line_closure:
|
||||
name: "Single line closure"
|
||||
regex: '\{([^\n\/]*\[[^\]]+\][^\n\/]*)?([^\n\/]*[a-zA-Z]\w*(, \w+)*)? in [^\n\/]+'
|
||||
message: "Too complex expression for single line closure. Improve readability by making it multiline."
|
||||
severity: error
|
||||
severity: warning
|
||||
|
||||
addSubview_in_cell:
|
||||
name: "Usage addSubview in cell"
|
||||
regex: '(extension|class)\s*\w+Cell(:| )(?s).*(self\.|\s{2,})add(Subv|V)iews?\(\w'
|
||||
message: "Use сontentView instead of self for addSubview or addSubviews methods in cell."
|
||||
severity: error
|
||||
severity: warning
|
||||
|
||||
redundant_type_annotation_bool:
|
||||
name: "Redundant type annotation for Bool"
|
||||
regex: '\s((var|let))\s{1,}\w+ *((: *Bool *=)|((\w| |<|>|:)*= *BehaviorRelay<Bool>\( *value *:)) *((true)|(false))'
|
||||
message: "Using a type annotation for Bool is redundant."
|
||||
severity: error
|
||||
severity: warning
|
||||
|
||||
parameter_repetition:
|
||||
name: "Parameter repetition"
|
||||
regex: 'func ((\w+([A-Z]\w+))|(\w+)) *(<[^>]+>)? *\( *(?i)(\3|\4):'
|
||||
message: "The parameter name is actually used in the function name. Use _ instead."
|
||||
severity: error
|
||||
severity: warning
|
||||
|
||||
parameter_closure:
|
||||
name: "Parameter closure"
|
||||
regex: '\w*Closure<[^\r\n\t\f\v]*, Void[^\r\n\t\f\v]*>'
|
||||
message: "Use `ParameterClosure` instead of declaring an explicit return value of `Void`."
|
||||
severity: warning
|
||||
|
||||
strong_self:
|
||||
name: "Strong self"
|
||||
regex: '(if|guard)\s+let\s+self\s+=\s+self'
|
||||
message: "Use a local function instead of capture strong self"
|
||||
severity: warning
|
||||
|
||||
pattern_matching:
|
||||
name: "Pattern matching"
|
||||
regex: 'case[^\n\(]+\([^\)]*(let|var)\s'
|
||||
message: "Use a let|var keyword behind parentheses"
|
||||
severity: warning
|
||||
|
||||
# Rx
|
||||
|
||||
|
|
@ -259,6 +275,12 @@ custom_rules:
|
|||
message: "Replace Rx.map operator with replace(with:) or asVoid(). For Sequence.map consider using forEach."
|
||||
severity: warning
|
||||
|
||||
disposable_nil:
|
||||
name: "Disposable nil"
|
||||
regex: ' *\S*(d|D)isposable\?? *= *nil'
|
||||
message: "nil assigning doesn't dispose subscription. Call `dispose()` instead."
|
||||
severity: error
|
||||
|
||||
# LeadKit
|
||||
|
||||
multiple_add_subview:
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
<?php
|
||||
$PRODUCT_NAME = $argv[1];
|
||||
$LOCALIZATION_PATH = $argv[1];
|
||||
$COMMON_STRINGS_PATH = $argv[2];
|
||||
$BUNDLE = $argv[3];
|
||||
|
||||
function createFolder($path) {
|
||||
if (!file_exists($path)) {
|
||||
mkdir($path, 0777, true);
|
||||
}
|
||||
}
|
||||
|
||||
$localization = './'.$PRODUCT_NAME.'/Resources/Localization/';
|
||||
|
||||
$baseFile = file_get_contents(array_pop(glob($COMMON_STRINGS_PATH.'/default*.json')));
|
||||
$baseJson = json_decode($baseFile, true);
|
||||
|
|
@ -31,25 +30,26 @@
|
|||
}
|
||||
$ios_strings = preg_replace('/(\\\\)(u)([0-9a-fA-F]{4})/', '$1U$3', $ios_strings);
|
||||
|
||||
$lproj = $localization.$languageName.'.lproj/';
|
||||
$lproj = $LOCALIZATION_PATH.$languageName.'.lproj/';
|
||||
createFolder($lproj);
|
||||
file_put_contents($lproj.'Localizable.strings', $ios_strings);
|
||||
|
||||
if($isBase) {
|
||||
createFolder($localization.'Base.lproj/');
|
||||
file_put_contents($localization.'Base.lproj/Localizable.strings', $ios_strings);
|
||||
createFolder($LOCALIZATION_PATH.'Base.lproj/');
|
||||
file_put_contents($LOCALIZATION_PATH.'Base.lproj/Localizable.strings', $ios_strings);
|
||||
$ios_swift_strings = 'import Foundation'.PHP_EOL.PHP_EOL.
|
||||
'// swiftlint:disable superfluous_disable_command'.PHP_EOL.
|
||||
'// swiftlint:disable line_length'.PHP_EOL.
|
||||
'// swiftlint:disable file_length'.PHP_EOL.
|
||||
'// swiftlint:disable cyrillic_strings'.PHP_EOL.
|
||||
'// swiftlint:disable identifier_name'.PHP_EOL.PHP_EOL.
|
||||
'public extension String {'.PHP_EOL;
|
||||
foreach ($json as $key=>$value) {
|
||||
$value_without_linefeed = preg_replace("/\r|\n/", " ", $value);
|
||||
$ios_swift_strings .= "\t/// ".$value_without_linefeed."\n\t".'static let '.preg_replace_callback('/_(.?)/', function ($m) { return strtoupper($m[1]); }, $key).' = NSLocalizedString("'.$key.'", comment: "")'."\n".PHP_EOL;
|
||||
$ios_swift_strings .= "\t/// ".$value_without_linefeed."\n\t".'static let '.preg_replace_callback('/_(.?)/', function ($m) { return strtoupper($m[1]); }, $key).' = NSLocalizedString("'.$key.'", bundle: '.$BUNDLE.', comment: "'.addslashes($value_without_linefeed).'")'."\n".PHP_EOL;
|
||||
}
|
||||
$ios_swift_strings .= '}'.PHP_EOL;
|
||||
file_put_contents($localization.'String+Localization.swift', $ios_swift_strings);
|
||||
file_put_contents($LOCALIZATION_PATH.'String+Localization.swift', $ios_swift_strings);
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Description:
|
||||
# Add user defined enviroment if programm not found
|
||||
#
|
||||
# Parameters:
|
||||
# $1 - programm
|
||||
#
|
||||
# Examples of usage:
|
||||
# . install_env.sh pmd
|
||||
#
|
||||
|
||||
# When you run Git from the command line, it runs in the environment as set up by your Shell.
|
||||
# GUI OS X apps, however, have no knowledge about your shell - and the PATH environment can be changed in many different places.
|
||||
# Export our profile with path by ourselves
|
||||
|
||||
function source_home_file {
|
||||
file="$HOME/$1"
|
||||
|
||||
if [[ -f "${file}" ]]; then
|
||||
if ! source "${file}"; then
|
||||
export_commands="$(cat "${file}" | grep "^export PATH=")"
|
||||
|
||||
while read export_command
|
||||
do
|
||||
eval "$export_command"
|
||||
done <<< "$export_commands"
|
||||
fi
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Use specific exec due to Xcode has custom value of $PATH
|
||||
if [ -z "$(which $1)" ]; then
|
||||
source_home_file ".bash_profile" || source_home_file ".zshrc" || source_home_file ".zprofile" || true
|
||||
|
||||
echo "User defined enviroment has been set for ${1}"
|
||||
fi
|
||||
|
|
@ -141,4 +141,4 @@ readonly DOWNLOAD_URL="https://maven.dev.touchin.ru/ru/touchin/api-generator/${V
|
|||
# execute api generator
|
||||
java -Xmx6g -jar "Downloads/${FILE_NAME}" generate-client-code --output-language SWIFT --specification-path common/api --output-path ${OUTPUT_PATH} --single-file true
|
||||
|
||||
record_current_commit
|
||||
record_current_commit
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -0,0 +1,93 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Description:
|
||||
# Converts SCRIPT_INPUT_FILE_{N} or SCRIPT_INPUT_FILE_LIST_{N} variables to string that contains
|
||||
# list of file names splitted by given separator.
|
||||
#
|
||||
# Parameters:
|
||||
# $1 - separator to use.
|
||||
# $2 - default value to return if SCRIPT_INPUT_FILE_COUNT or SCRIPT_INPUT_FILE_LIST_COUNT is zero.
|
||||
#
|
||||
# Optional environment variables:
|
||||
# FILE_NAMES_SEPARATOR - separator to use.
|
||||
# DEFAULT_FILE_NAMES - default value if was found in environment variables.
|
||||
# SCRIPT_INPUT_FILE_COUNT - number of files listed in "Input files" section of build phase.
|
||||
# SCRIPT_INPUT_FILE_{N} - file path of specific input file at index.
|
||||
# SCRIPT_INPUT_FILE_LIST_COUNT - number of files listed in "Input File Lists" section of build phase.
|
||||
# SCRIPT_INPUT_FILE_LIST_{N} - file path to specifis xcfilelist file at index.
|
||||
#
|
||||
# Examples of usage:
|
||||
# read_input_file_names
|
||||
# read_input_file_names.sh " " path/to/project
|
||||
#
|
||||
|
||||
has_input_files()
|
||||
{
|
||||
[ ! -z "${SCRIPT_INPUT_FILE_COUNT}" ] && [ ${SCRIPT_INPUT_FILE_COUNT} -gt 0 ]
|
||||
}
|
||||
|
||||
has_input_file_lists()
|
||||
{
|
||||
[ ! -z "${SCRIPT_INPUT_FILE_LIST_COUNT}" ] && [ ${SCRIPT_INPUT_FILE_LIST_COUNT} -gt 0 ]
|
||||
}
|
||||
|
||||
if [ -z "${FILE_NAMES_SEPARATOR}" ]; then
|
||||
if [ ! -z "${1}" ]; then
|
||||
FILE_NAMES_SEPARATOR=${1}
|
||||
else
|
||||
FILE_NAMES_SEPARATOR=" "
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "${DEFAULT_FILE_NAMES}" ]; then
|
||||
if [ ! -z "${2}" ]; then
|
||||
DEFAULT_FILE_NAMES=${2}
|
||||
else
|
||||
DEFAULT_FILE_NAMES=""
|
||||
fi
|
||||
fi
|
||||
|
||||
INPUT_FILE_NAMES=""
|
||||
|
||||
if has_input_files && has_input_file_lists; then
|
||||
>&2 echo "Passing Input Files and Input Files Lists is not supported!\nOnly Input Files will be used."
|
||||
fi
|
||||
|
||||
if has_input_files && \
|
||||
[ ${SCRIPT_INPUT_FILE_COUNT} -gt 0 ]; then
|
||||
|
||||
for i in `seq 0 $((${SCRIPT_INPUT_FILE_COUNT}-1))`
|
||||
do
|
||||
SCRIPT_INPUT_FILE_VARIABLE_NAME="SCRIPT_INPUT_FILE_${i}"
|
||||
SHELL_VARIABLE="\${${SCRIPT_INPUT_FILE_VARIABLE_NAME}}"
|
||||
RESOLVED_FILE_NAME=`envsubst <<< ${SHELL_VARIABLE}`
|
||||
INPUT_FILE_NAMES=${INPUT_FILE_NAMES}${FILE_NAMES_SEPARATOR}${RESOLVED_FILE_NAME}
|
||||
done
|
||||
|
||||
FILE_NAMES_SEPARATOR_LENGTH=`awk '{ print length; }' <<< "${FILE_NAMES_SEPARATOR}"`
|
||||
|
||||
if [ ${FILE_NAMES_SEPARATOR_LENGTH} -gt 0 ] && \
|
||||
[ ! -z "${INPUT_FILE_NAMES}" ]; then
|
||||
|
||||
# remove separator prefix
|
||||
INPUT_FILE_NAMES=`cut -c${FILE_NAMES_SEPARATOR_LENGTH}- <<< ${INPUT_FILE_NAMES}`
|
||||
fi
|
||||
elif has_input_file_lists; then
|
||||
for i in `seq 0 $((${SCRIPT_INPUT_FILE_LIST_COUNT}-1))`
|
||||
do
|
||||
SCRIPT_INPUT_FILE_LIST_VARIABLE_NAME="SCRIPT_INPUT_FILE_LIST_${i}"
|
||||
SHELL_VARIABLE="\${${SCRIPT_INPUT_FILE_LIST_VARIABLE_NAME}}"
|
||||
FILE_NAME=`envsubst <<< ${SHELL_VARIABLE}`
|
||||
RESOLVED_FILE_NAMES=`envsubst < ${FILE_NAME}`
|
||||
|
||||
for INPUT_FILE_NAME in ${RESOLVED_FILE_NAMES}; do
|
||||
INPUT_FILE_NAMES=${INPUT_FILE_NAMES}${INPUT_FILE_NAME}${FILE_NAMES_SEPARATOR}
|
||||
done
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -z "${INPUT_FILE_NAMES}" ]; then
|
||||
echo ${DEFAULT_FILE_NAMES}
|
||||
else
|
||||
echo ${INPUT_FILE_NAMES}
|
||||
fi
|
||||
Binary file not shown.
|
|
@ -1,20 +1,61 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Description:
|
||||
# Validates code for copy-paste, prints results to standard output and report file.
|
||||
#
|
||||
# Parameters:
|
||||
# $1 $2 $3 $n - folders to exclude from code checking.
|
||||
#
|
||||
# Required environment variables:
|
||||
# PROJECT_DIR - project directory.
|
||||
# SCRIPT_DIR - directory of current script.
|
||||
#
|
||||
# Optional environment variables:
|
||||
# SCRIPT_INPUT_FILE_COUNT - number of files listed in "Input files" of build phase.
|
||||
# SCRIPT_INPUT_FILE_{N} - file path to directory that should be checked.
|
||||
#
|
||||
# Modified files:
|
||||
# ${PROJECT_DIR}/code-quality-reports/CPDLog.txt - check report.
|
||||
#
|
||||
# Example of usage:
|
||||
# runner.sh copy_paste_detection.sh Generated Localization Pods
|
||||
#
|
||||
|
||||
readonly EXIT_SUCCESS=0
|
||||
readonly EXIT_FAILURE=1
|
||||
|
||||
. ${SCRIPT_DIR}/../aux_scripts/install_env.sh pmd
|
||||
|
||||
if which pmd >/dev/null; then
|
||||
# running CPD
|
||||
readonly SOURCES_DIR=${1:-${PROJECT_DIR}} # first argument or PROJECT_DIR
|
||||
readonly REPORTS_DIR=${PROJECT_DIR}/code-quality-reports
|
||||
readonly FILES_TO_EXCLUDE=`find ${SOURCES_DIR} -type d -name Localization -or -name Generated -or -name Carthage -or -name Pods | paste -sd " " -`
|
||||
readonly REPORTS_DIR="${PROJECT_DIR}/code-quality-reports"
|
||||
|
||||
mkdir ${REPORTS_DIR}
|
||||
readonly SOURCES_DIRS=`. ${SCRIPT_DIR}/common/read_input_file_names.sh " " ${PROJECT_DIR}`
|
||||
|
||||
pmd cpd --files ${SOURCES_DIR} --exclude ${FILES_TO_EXCLUDE} --minimum-tokens 50 --language swift --encoding UTF-8 --format net.sourceforge.pmd.cpd.XMLRenderer > ${REPORTS_DIR}/cpd-output.xml --failOnViolation true
|
||||
readonly COMMAND_LINE_ARGUMENTS=$@
|
||||
|
||||
php ./build-scripts/xcode/aux_scripts/cpd_script.php ${REPORTS_DIR}/cpd-output.xml | tee ${REPORTS_DIR}/CPDLog.txt
|
||||
FOLDERS_TO_EXLUDE=""
|
||||
|
||||
# Make paths relative to SOURCES_DIR, so different developers won't rewrite entire file
|
||||
readonly SED_REPLACEMENT_STRING=$(echo ${SOURCES_DIR} | sed "s/\//\\\\\//g")
|
||||
for argument in ${COMMAND_LINE_ARGUMENTS}
|
||||
do
|
||||
FOLDERS_TO_EXLUDE=${FOLDERS_TO_EXLUDE}"-or -name ${argument} "
|
||||
done
|
||||
|
||||
FOLDERS_TO_EXLUDE=`echo ${FOLDERS_TO_EXLUDE} | cut -c5-` # remove first "-or"
|
||||
|
||||
readonly FILES_TO_EXCLUDE=`find ${PROJECT_DIR} -type d ${FOLDERS_TO_EXLUDE} | paste -sd " " -`
|
||||
|
||||
mkdir -p ${REPORTS_DIR}
|
||||
|
||||
pmd cpd --files ${SOURCES_DIRS} --exclude ${FILES_TO_EXCLUDE} --minimum-tokens 50 --language swift --encoding UTF-8 --format net.sourceforge.pmd.cpd.XMLRenderer --failOnViolation true > ${REPORTS_DIR}/cpd-output.xml
|
||||
|
||||
php ${SCRIPT_DIR}/../aux_scripts/cpd_script.php ${REPORTS_DIR}/cpd-output.xml | tee ${REPORTS_DIR}/CPDLog.txt
|
||||
|
||||
# Make paths relative to PROJECT_DIR, so different developers won't rewrite entire file
|
||||
readonly SED_REPLACEMENT_STRING=$(echo ${PROJECT_DIR} | sed "s/\//\\\\\//g")
|
||||
|
||||
sed -i '' "s/${SED_REPLACEMENT_STRING}//g" "${REPORTS_DIR}/CPDLog.txt"
|
||||
else
|
||||
echo "warning: pmd not installed, install using 'brew install pmd'"
|
||||
exit 1
|
||||
|
||||
exit ${EXIT_FAILURE}
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
require 'yaml'
|
||||
|
||||
require_relative '../../managers/managers'
|
||||
require_relative '../../templates/templates'
|
||||
|
||||
# Input files paths
|
||||
build_settings_file_path = ARGV[0]
|
||||
generated_features_enum_file_path = ARGV[1]
|
||||
|
||||
build_settings_features_list = Managers::FileManager.load_from_file_YAML(build_settings_file_path)["features"]
|
||||
|
||||
if build_settings_features_list.nil? or build_settings_features_list.empty?
|
||||
raise "There are no features in " + build_settings_file_path
|
||||
end
|
||||
|
||||
# Generate enum Feature Toggles
|
||||
features_enum_template = Templates::FeatureTemplates.features_enum
|
||||
utils = Managers::TemplateManager.new(build_settings_features_list)
|
||||
|
||||
rendered_enum = utils.render(features_enum_template).strip
|
||||
|
||||
Managers::FileManager.save_data_to_file(generated_features_enum_file_path, rendered_enum)
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# Input paths
|
||||
readonly BUILD_SETTINGS_FILE_PATH=${1:-${PROJECT_DIR}/common/build_settings.yaml}
|
||||
readonly FEATURES_ENUM_FILE_PATH=${2:-${PROJECT_DIR}/${PRODUCT_NAME}/Resources/Features/Feature.swift}
|
||||
|
||||
# Features enunm generator script
|
||||
readonly CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
readonly GENERATOR_SCRIPT=${CURRENT_DIR}/features_generator.rb
|
||||
|
||||
if ! [ -e ${BUILD_SETTINGS_FILE_PATH} ]; then
|
||||
echo "File ${BUILD_SETTINGS_FILE_PATH} does not exist. Add this file and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [ -e ${FEATURES_ENUM_FILE_PATH} ]; then
|
||||
echo "File ${FEATURES_ENUM_FILE_PATH} does not exist. Add this file and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ruby ${GENERATOR_SCRIPT} ${BUILD_SETTINGS_FILE_PATH} ${FEATURES_ENUM_FILE_PATH}
|
||||
|
|
@ -1,16 +1,47 @@
|
|||
LOCALIZATION_PATH="${PRODUCT_NAME}/Resources/Localization"
|
||||
#first argument set strings folder path
|
||||
#!/bin/sh
|
||||
|
||||
# Description:
|
||||
# Generates Localizeable.strings and String+Localization.swift files.
|
||||
#
|
||||
# Parameters:
|
||||
# $1 - path to strings folder containing json files.
|
||||
# $2 - path to Localization folder (output).
|
||||
# $3 - Bundle for localization. Default is `.main`.
|
||||
#
|
||||
# Required environment variables:
|
||||
# SCRIPT_DIR - directory of current script.
|
||||
#
|
||||
# Optional environment variables:
|
||||
# PRODUCT_NAME - product name to produce path to localization folder (output).
|
||||
#
|
||||
# Examples of usage:
|
||||
# . localization.sh
|
||||
# . localization.sh common/strings Resources/Localization/ .main
|
||||
#
|
||||
|
||||
readonly EXIT_SUCCESS=0
|
||||
readonly EXIT_FAILURE=1
|
||||
|
||||
. ${SCRIPT_DIR}/../aux_scripts/install_env.sh php
|
||||
|
||||
STRINGS_FOLDER=${1:-"common/strings"}
|
||||
LOCALIZATION_PATH=${2:-"${PRODUCT_NAME}/Resources/Localization/"}
|
||||
BUNDLE=${3:-".main"}
|
||||
|
||||
if ! [ -e ${LOCALIZATION_PATH} ]; then
|
||||
echo "${PROJECT_DIR}/${LOCALIZATION_PATH} path does not exist. Add these folders and try again."
|
||||
exit 1
|
||||
echo "${LOCALIZATION_PATH} path does not exist. Add these folders and try again."
|
||||
exit ${EXIT_FAILURE}
|
||||
fi
|
||||
|
||||
if ! [ -e "${PROJECT_DIR}/${STRINGS_FOLDER}" ]; then
|
||||
echo "${PROJECT_DIR}/${STRINGS_FOLDER} path does not exist. Submodule with strings should be named common and contain strings folder."
|
||||
exit 1
|
||||
if ! [ -e "${STRINGS_FOLDER}" ]; then
|
||||
echo "${STRINGS_FOLDER} path does not exist. Submodule with strings should be named common and contain strings folder."
|
||||
exit ${EXIT_FAILURE}
|
||||
fi
|
||||
|
||||
#second argument set strings script path
|
||||
php ${2:-build-scripts/xcode/aux_scripts/import_strings.php} ${PRODUCT_NAME} ${STRINGS_FOLDER}
|
||||
if which php >/dev/null; then
|
||||
php ${SCRIPT_DIR}/../aux_scripts/import_strings.php ${LOCALIZATION_PATH} ${STRINGS_FOLDER} ${BUNDLE}
|
||||
else
|
||||
echo "warning: php not installed, install using 'brew install php'"
|
||||
|
||||
exit ${EXIT_FAILURE}
|
||||
fi
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# source: https://github.com/iKenndac/verify-string-files
|
||||
|
||||
# first argument set base localization strings path
|
||||
readonly LOCALIZATION_PATH=${1:-${PRODUCT_NAME}/Resources/Localization/Base.lproj/Localizable.strings}
|
||||
|
||||
# second argument set check script path
|
||||
readonly CHECK_SCRIPT=${2:-${PROJECT_DIR}/build-scripts/xcode/build_phases/common/localization_check}
|
||||
|
||||
${CHECK_SCRIPT} -master ${LOCALIZATION_PATH}
|
||||
|
|
@ -7,17 +7,50 @@ class SettingOption
|
|||
def initialize
|
||||
@options = OpenStruct.new
|
||||
OptionParser.new do |opt|
|
||||
opt.on('-p', '--project_root_path STRING', 'The path of project directory and contains *.xcodeproj file always. ' +
|
||||
'Example: project_root_path=~/Projects/MyProject/Source/..') { |option| @options.project_root_path = option }
|
||||
opt.on('-r', '--source_root_path STRING', 'The path of source directory and may not contains *.xcodeproj file in some cases. ' +
|
||||
'Example: source_root_path=~/Projects/MyProject/') { |option| @options.source_root_path = option }
|
||||
opt.on('-s', '--swiftlint_executable_path STRING', 'The executable path of swiftlint') { |option| @options.swiftlint_executable_path = option }
|
||||
opt.on('-c', '--check_mode MODE', 'The mode of check is "fully" or "simplified"') { |option| @options.check_mode = option }
|
||||
opt.on('-u', '--use_multiple BOOL', 'The flag indicates the use of multiple yaml swiftlint configurations') { |option| @options.use_multiple = option }
|
||||
opt.on('-d', '--source_date DATE', 'The date of grouping files according touchin and old swiftlint rules') { |option| @options.source_date = option }
|
||||
opt.on('-y', '--touchin_swiftlint_yaml_path STRING', 'The path to the touchin swiftlint yaml relative to the source directory') { |option| @options.touchin_swiftlint_yaml_path = option }
|
||||
opt.on('-p',
|
||||
'--project_root_path STRING',
|
||||
'The path of project directory and contains *.xcodeproj file always. ' +
|
||||
'Example: project_root_path=~/Projects/MyProject/Source/..') { |option|
|
||||
@options.project_root_path = option
|
||||
}
|
||||
opt.on('-r',
|
||||
'--source_root_path STRING',
|
||||
'The path of source directory and may not contains *.xcodeproj file in some cases. ' +
|
||||
'Example: source_root_path=~/Projects/MyProject/') { |option|
|
||||
@options.source_root_path = option
|
||||
}
|
||||
opt.on('-s',
|
||||
'--swiftlint_executable_path STRING',
|
||||
'The executable path of swiftlint') { |option|
|
||||
@options.swiftlint_executable_path = option
|
||||
}
|
||||
opt.on('-c',
|
||||
'--check_mode MODE',
|
||||
'The mode of check is "fully" or "simplified"') { |option|
|
||||
@options.check_mode = option
|
||||
}
|
||||
opt.on('-u',
|
||||
'--use_multiple BOOL',
|
||||
'The flag indicates the use of multiple yaml swiftlint configurations') { |option|
|
||||
@options.use_multiple = option
|
||||
}
|
||||
opt.on('-d',
|
||||
'--source_date DATE',
|
||||
'The date of grouping files according touchin and old swiftlint rules') { |option|
|
||||
@options.source_date = option
|
||||
}
|
||||
opt.on('-tc',
|
||||
'--touchin_swiftlint_yaml_path STRING',
|
||||
'The path to the touchin swiftlint yaml relative to the source directory') { |option|
|
||||
@options.touchin_swiftlint_yaml_path = option
|
||||
}
|
||||
opt.on('-oc',
|
||||
'--old_swiftlint_yaml_path STRING',
|
||||
'The path to the old swiftlint yaml relative to the source directory') { |option|
|
||||
@options.old_swiftlint_yaml_path = option
|
||||
}
|
||||
end.parse!
|
||||
|
||||
|
||||
if @options.check_mode.to_s.nilOrEmpty?
|
||||
@options.check_mode = 'fully'
|
||||
end
|
||||
|
|
@ -29,37 +62,17 @@ class SettingOption
|
|||
if @options.source_root_path.to_s.nilOrEmpty?
|
||||
@options.source_root_path = @options.project_root_path
|
||||
end
|
||||
|
||||
|
||||
if @options.touchin_swiftlint_yaml_path.to_s.nilOrEmpty?
|
||||
@options.touchin_swiftlint_yaml_path = '/build-scripts/xcode/.swiftlint.yml'
|
||||
@options.touchin_swiftlint_yaml_path = File.join(project_root_path, 'build-scripts/xcode/.swiftlint.yml')
|
||||
end
|
||||
|
||||
if @options.old_swiftlint_yaml_path.to_s.nilOrEmpty?
|
||||
@options.old_swiftlint_yaml_path = File.join(project_root_path, '.swiftlint.yml')
|
||||
end
|
||||
end
|
||||
|
||||
def project_root_path
|
||||
@options.project_root_path
|
||||
end
|
||||
|
||||
def source_date
|
||||
@options.source_date
|
||||
end
|
||||
|
||||
def swiftlint_executable_path
|
||||
@options.swiftlint_executable_path
|
||||
end
|
||||
|
||||
def check_mode
|
||||
@options.check_mode
|
||||
end
|
||||
|
||||
def use_multiple
|
||||
@options.use_multiple
|
||||
end
|
||||
|
||||
def source_root_path
|
||||
@options.source_root_path
|
||||
end
|
||||
|
||||
def touchin_swiftlint_yaml_path
|
||||
@options.touchin_swiftlint_yaml_path
|
||||
|
||||
def method_missing(method, *args, &block)
|
||||
@options.send(method, *args, &block)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
require 'fileutils'
|
||||
require 'tmpdir'
|
||||
|
||||
require_relative 'array_extension.rb'
|
||||
require_relative 'git_caretaker.rb'
|
||||
|
|
@ -7,19 +8,19 @@ require_relative 'swift_file_manager.rb'
|
|||
require_relative 'yaml_manager.rb'
|
||||
|
||||
class StrategyMaker
|
||||
def initialize(project_root_path, swiftlint_executable_path, touchin_swiftlint_yaml_path)
|
||||
@project_root_path = project_root_path
|
||||
@touchin_swiftlint_yaml_path = project_root_path + touchin_swiftlint_yaml_path
|
||||
@old_swiftlint_yaml_path = project_root_path + '/.swiftlint.yml'
|
||||
|
||||
@temporary_swiftlint_folder_name = project_root_path + '/temporary_swiftlint'
|
||||
@touchin_swiftlint_yaml_temporary_path = @temporary_swiftlint_folder_name + '/.touchin_swiftlint.yml'
|
||||
@old_swiftlint_yaml_temporary_path = @temporary_swiftlint_folder_name + '/.old_swiftlint.yml'
|
||||
|
||||
def initialize(project_root_path, swiftlint_executable_path, touchin_swiftlint_yaml_path, old_swiftlint_yaml_path)
|
||||
@project_root_path = project_root_path
|
||||
@touchin_swiftlint_yaml_path = touchin_swiftlint_yaml_path
|
||||
@old_swiftlint_yaml_path = old_swiftlint_yaml_path
|
||||
|
||||
@temporary_swiftlint_folder_name = Dir.mktmpdir
|
||||
@touchin_swiftlint_yaml_temporary_path = File.join(@temporary_swiftlint_folder_name, '.touchin_swiftlint.yml')
|
||||
@old_swiftlint_yaml_temporary_path = File.join(@temporary_swiftlint_folder_name, '.old_swiftlint.yml')
|
||||
|
||||
@swiftlint_autocorrect_command = swiftlint_executable_path + ' autocorrect --path ' + @project_root_path + ' --config '
|
||||
@swiftlint_lint_command = swiftlint_executable_path + ' --path ' + @project_root_path + ' --config '
|
||||
end
|
||||
|
||||
|
||||
def run_fully_multiple_strategy(source_date)
|
||||
create_yaml_managers_and_copy_temporary_files
|
||||
|
||||
|
|
@ -33,38 +34,38 @@ class StrategyMaker
|
|||
|
||||
@touchin_swiftlint_yaml_manager.update('excluded', total_touchin_excluded_files)
|
||||
@old_swiftlint_yaml_manager.update('excluded', total_old_excluded_files)
|
||||
|
||||
|
||||
run_multiple_strategy(@touchin_swiftlint_yaml_temporary_path, @old_swiftlint_yaml_temporary_path)
|
||||
end
|
||||
|
||||
|
||||
def run_simplified_multiple_strategy(source_date, source_root_path)
|
||||
included_files = GitСaretaker.get_modified_files
|
||||
|
||||
|
||||
if included_files.nilOrEmpty?
|
||||
puts 'Git did not found swift files to check'
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
create_yaml_managers_and_copy_temporary_files
|
||||
|
||||
exclude_files = unique_exclude_files(@touchin_swiftlint_yaml_manager, @old_swiftlint_yaml_manager)
|
||||
included_files = included_files.map { |file_path| source_root_path + file_path }
|
||||
|
||||
|
||||
swift_file_manager = SwiftFileManager.new(exclude_files, source_date)
|
||||
swift_file_manager.find_list_file_paths_from(included_files)
|
||||
|
||||
|
||||
total_touchin_included_files = swift_file_manager.new_files
|
||||
total_old_included_files = swift_file_manager.old_files
|
||||
|
||||
|
||||
@touchin_swiftlint_yaml_manager.update('excluded', [])
|
||||
@old_swiftlint_yaml_manager.update('excluded', [])
|
||||
|
||||
|
||||
@touchin_swiftlint_yaml_manager.update('included', total_touchin_included_files)
|
||||
@old_swiftlint_yaml_manager.update('included', total_old_included_files)
|
||||
|
||||
|
||||
is_exist_total_touchin_included_files = (not total_touchin_included_files.nilOrEmpty?)
|
||||
is_exist_total_old_included_files = (not total_old_included_files.nilOrEmpty?)
|
||||
|
||||
|
||||
if is_exist_total_touchin_included_files and is_exist_total_old_included_files
|
||||
run_multiple_strategy(@touchin_swiftlint_yaml_temporary_path, @old_swiftlint_yaml_temporary_path)
|
||||
elsif is_exist_total_touchin_included_files and not is_exist_total_old_included_files
|
||||
|
|
@ -75,11 +76,11 @@ class StrategyMaker
|
|||
puts 'Git did not found swift files to check'
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def run_fully_single_strategy
|
||||
run_single_strategy(@touchin_swiftlint_yaml_path)
|
||||
end
|
||||
|
||||
|
||||
def run_simplified_single_strategy(source_root_path)
|
||||
included_files = GitСaretaker.get_modified_files
|
||||
|
||||
|
|
@ -87,34 +88,34 @@ class StrategyMaker
|
|||
puts 'Git did not found swift files to check'
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
create_copy_temporary_touchin_files
|
||||
|
||||
|
||||
touchin_swiftlint_yaml_manager = YamlManager.new(@touchin_swiftlint_yaml_temporary_path)
|
||||
touchin_excluded_files = touchin_swiftlint_yaml_manager.get_configuration('excluded')
|
||||
swift_files = SwiftFileManager.new(touchin_excluded_files, '')
|
||||
|
||||
included_files = included_files.select { |file_name| not swift_files.is_excluded_file(file_name) }
|
||||
included_files = included_files.map { |file_path| source_root_path + file_path }
|
||||
|
||||
|
||||
touchin_swiftlint_yaml_manager.update('excluded', [])
|
||||
touchin_swiftlint_yaml_manager.update('included', included_files)
|
||||
|
||||
|
||||
if not included_files.nilOrEmpty?
|
||||
run_single_strategy(@touchin_swiftlint_yaml_temporary_path)
|
||||
else
|
||||
puts 'Git found the swift files to check, but they are excluded in yaml'
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
|
||||
def run_single_strategy(swiftlint_yaml_path)
|
||||
result_swiftlint_command = get_swiftlint_command(swiftlint_yaml_path)
|
||||
puts result_swiftlint_command
|
||||
run_bash_command(result_swiftlint_command)
|
||||
end
|
||||
|
||||
|
||||
def run_multiple_strategy(touchin_swiftlint_yaml_temporary_path, old_swiftlint_yaml_temporary_path)
|
||||
touchin_swiftlint_command = get_swiftlint_command(touchin_swiftlint_yaml_temporary_path)
|
||||
old_swiftlint_command = get_swiftlint_command(old_swiftlint_yaml_temporary_path)
|
||||
|
|
@ -122,34 +123,34 @@ class StrategyMaker
|
|||
puts result_swiftlint_command
|
||||
run_bash_command(result_swiftlint_command)
|
||||
end
|
||||
|
||||
|
||||
def get_swiftlint_command(swiftlint_yaml_path)
|
||||
autocorrect_command = @swiftlint_autocorrect_command + swiftlint_yaml_path
|
||||
lint_command = @swiftlint_lint_command + swiftlint_yaml_path
|
||||
return autocorrect_command + ' && ' + lint_command
|
||||
end
|
||||
|
||||
|
||||
def run_bash_command(bash_command)
|
||||
exit (exec bash_command)
|
||||
end
|
||||
|
||||
def create_yaml_managers_and_copy_temporary_files
|
||||
create_copy_temporary_files
|
||||
|
||||
|
||||
@touchin_swiftlint_yaml_manager = YamlManager.new(@touchin_swiftlint_yaml_temporary_path)
|
||||
@old_swiftlint_yaml_manager = YamlManager.new(@old_swiftlint_yaml_temporary_path)
|
||||
end
|
||||
|
||||
|
||||
def create_copy_temporary_files
|
||||
create_copy_temporary_touchin_files
|
||||
FileUtils.cp @old_swiftlint_yaml_path, @old_swiftlint_yaml_temporary_path
|
||||
end
|
||||
|
||||
|
||||
def create_copy_temporary_touchin_files
|
||||
Dir.mkdir(@temporary_swiftlint_folder_name) unless Dir.exist?(@temporary_swiftlint_folder_name)
|
||||
FileUtils.cp @touchin_swiftlint_yaml_path, @touchin_swiftlint_yaml_temporary_path
|
||||
end
|
||||
|
||||
|
||||
def unique_exclude_files(touchin_swiftlint_yaml_manager, old_swiftlint_yaml_manager)
|
||||
touchin_excluded_files = touchin_swiftlint_yaml_manager.get_configuration('excluded')
|
||||
old_excluded_files = old_swiftlint_yaml_manager.get_configuration('excluded')
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@ require_relative 'setting_option.rb'
|
|||
require_relative 'strategy_maker.rb'
|
||||
|
||||
setting = SettingOption.new
|
||||
strategy_maker = StrategyMaker.new(setting.project_root_path, setting.swiftlint_executable_path, setting.touchin_swiftlint_yaml_path)
|
||||
strategy_maker = StrategyMaker.new(setting.project_root_path,
|
||||
setting.swiftlint_executable_path,
|
||||
setting.touchin_swiftlint_yaml_path,
|
||||
setting.old_swiftlint_yaml_path)
|
||||
|
||||
if setting.check_mode.eql? 'fully' and setting.use_multiple.true?
|
||||
strategy_maker.run_fully_multiple_strategy(setting.source_date)
|
||||
|
|
|
|||
|
|
@ -1,2 +1,86 @@
|
|||
SOURCES_DIR=${1:-${TARGET_NAME}} # first argument or TARGET_NAME
|
||||
${PODS_ROOT}/SwiftLint/swiftlint autocorrect --path ${SOURCES_DIR} --config ${PROJECT_DIR}/build-scripts/xcode/.swiftlint.yml && ${PODS_ROOT}/SwiftLint/swiftlint --path ${SOURCES_DIR} --config ${PROJECT_DIR}/build-scripts/xcode/.swiftlint.yml
|
||||
#!/bin/sh
|
||||
|
||||
# Description:
|
||||
# Runs swiftlint with selected or default config file.
|
||||
#
|
||||
# Parameters:
|
||||
# $1 - path to swiftlint executable.
|
||||
# $2 - path to swiftlint config.
|
||||
#
|
||||
# Required environment variables:
|
||||
# SCRIPT_DIR - directory of current script.
|
||||
# SRCROOT - project directory.
|
||||
# PODS_ROOT - cocoapods installation directory (eg. ${SRCROOT}/Pods).
|
||||
#
|
||||
# Optional environment variables:
|
||||
# SWIFTLINT_EXECUTABLE - path to swiftlint executable.
|
||||
# SWIFTLINT_CONFIG_PATH - path to swiftlint config.
|
||||
# SCRIPT_INPUT_FILE_COUNT - number of files listed in "Input files" of build phase.
|
||||
# SCRIPT_INPUT_FILE_{N} - file path to directory that should be checked.
|
||||
# FORCE_LINT - lint all project.
|
||||
#
|
||||
# Example of usage:
|
||||
# swiftlint.sh
|
||||
# FORCE_LINT=true; swiftlint.sh
|
||||
# swiftlint.sh Pods/Swiftlint/swiftlint build-scripts/xcode/.swiftlint.yml
|
||||
#
|
||||
|
||||
readonly SOURCES_DIRS=`. ${SCRIPT_DIR}/common/read_input_file_names.sh "\n" ${SRCROOT}`
|
||||
|
||||
if [ -z "${SWIFTLINT_EXECUTABLE}" ]; then
|
||||
if [ ! -z "${1}" ]; then
|
||||
readonly SWIFTLINT_EXECUTABLE=${1}
|
||||
else
|
||||
readonly SWIFTLINT_EXECUTABLE=${PODS_ROOT}/SwiftLint/swiftlint
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "${SWIFTLINT_CONFIG_PATH}" ]; then
|
||||
if [ ! -z "${2}" ]; then
|
||||
readonly SWIFTLINT_CONFIG_PATH=${2}
|
||||
else
|
||||
readonly SWIFTLINT_CONFIG_PATH=${SCRIPT_DIR}/../.swiftlint.yml
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -z "${FORCE_LINT}" ]; then
|
||||
# Если задана переменная FORCE_LINT, то проверяем все файлы проекта
|
||||
for SOURCE_DIR in ${SOURCES_DIRS}; do
|
||||
${SWIFTLINT_EXECUTABLE} autocorrect --path ${SOURCE_DIR} --config ${SWIFTLINT_CONFIG_PATH}
|
||||
${SWIFTLINT_EXECUTABLE} --path ${SOURCE_DIR} --config ${SWIFTLINT_CONFIG_PATH}
|
||||
done
|
||||
else
|
||||
# Xcode упадет, если будем использовать большое количество Script Input Files,
|
||||
# так как просто переполнится стек - https://unix.stackexchange.com/questions/357843/setting-a-long-environment-variable-breaks-a-lot-of-commands
|
||||
# Поэтому воспользуемся "скрытым" параметром Swiflint - https://github.com/realm/SwiftLint/pull/3313
|
||||
# Создадим временный файл swiftlint_files с префиксом @ и в нем уже определим список файлов
|
||||
# необходимых для линтовки :)
|
||||
|
||||
lint_files_path="${SRCROOT}/build_phases/swiftlint_files"
|
||||
|
||||
# Если файл существует, то просто его очистим, если нет - создадим
|
||||
> ${lint_files_path}
|
||||
|
||||
# Проходимся по папкам, которые требуют линтовки
|
||||
for SOURCE_DIR in ${SOURCES_DIRS}; do
|
||||
# Путь к папке репозитория
|
||||
path_prefix="`git rev-parse --show-toplevel`/"
|
||||
|
||||
# Отбираем файлы, которые были изменены или созданы
|
||||
source_unstaged_files=$(git diff --diff-filter=d --name-only --line-prefix=${path_prefix} ${SOURCE_DIR} | grep "\.swift$")
|
||||
source_staged_files=$(git diff --diff-filter=d --name-only --line-prefix=${path_prefix} --cached ${SOURCE_DIR} | grep "\.swift$")
|
||||
|
||||
if [ ! -z "${source_unstaged_files}" ]; then
|
||||
echo "${source_unstaged_files}" >> ${lint_files_path}
|
||||
fi
|
||||
|
||||
if [ ! -z "${source_staged_files}" ]; then
|
||||
echo "${source_staged_files}" >> ${lint_files_path}
|
||||
fi
|
||||
done
|
||||
|
||||
swiftlint_files_path="@${lint_files_path}"
|
||||
|
||||
${SWIFTLINT_EXECUTABLE} autocorrect --path ${swiftlint_files_path} --config ${SWIFTLINT_CONFIG_PATH} --force-exclude --use-alternative-excluding
|
||||
${SWIFTLINT_EXECUTABLE} --path ${swiftlint_files_path} --config ${SWIFTLINT_CONFIG_PATH} --force-exclude --use-alternative-excluding
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
arguments=("$@")
|
||||
ignored_files=$(IFS=, ; echo "${arguments[*]}")
|
||||
readonly ARGUMENTS=("$@")
|
||||
readonly IGNORED_FILES=$(IFS=, ; echo "${ARGUMENTS[*]}")
|
||||
readonly SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
|
||||
ruby ${PROJECT_DIR}/build-scripts/xcode/build_phases/Unused.rb --config ${PROJECT_DIR}/build-scripts/xcode/UnusedConfig.yml --exclude ${ignored_files}
|
||||
ruby ${SCRIPT_DIR}/Unused.rb --config ${SCRIPT_DIR}/../UnusedConfig.yml --exclude ${IGNORED_FILES}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
readonly SOURCES_DIR=${1:-${PROJECT_DIR}/${PRODUCT_NAME}} # first argument set product dir
|
||||
readonly UNUSED_RESOURCES_SCRIPT=${2:-${PROJECT_DIR}/build-scripts/xcode/build_phases/common/unused_resources} # second argument set script path
|
||||
readonly REPORTS_DIR=${PROJECT_DIR}/code-quality-reports
|
||||
readonly FILES_TO_EXCLUDE=`find ${SOURCES_DIR} -type d -name Localization -or -name Generated | paste -sd " " -`
|
||||
|
||||
mkdir ${REPORTS_DIR}
|
||||
|
||||
${UNUSED_RESOURCES_SCRIPT} --project ${SOURCES_DIR} --exclude ${FILES_TO_EXCLUDE} --action "l" > ${REPORTS_DIR}/Unused_resources_log.txt
|
||||
|
|
@ -1,6 +1,15 @@
|
|||
$appName = File.basename(Dir['../*.xcworkspace'].first, '.*')
|
||||
|
||||
require_relative 'fastlane/touchlane/lib/touchlane'
|
||||
require_relative 'managers/managers'
|
||||
|
||||
# ugly hack to add support for custom storage
|
||||
|
||||
Match.module_eval do
|
||||
def self.storage_modes
|
||||
return %w(git google_cloud s3 local)
|
||||
end
|
||||
end
|
||||
|
||||
# ugly hack to add support for custom storage
|
||||
|
||||
|
|
@ -19,49 +28,15 @@ private_lane :installDependencies do |options|
|
|||
sh("rm -rf #{podsReposPath}")
|
||||
end
|
||||
|
||||
if File.exists? "../Gemfile"
|
||||
bundle_install(path: "../.gem")
|
||||
end
|
||||
|
||||
cocoapods(
|
||||
repo_update: true
|
||||
)
|
||||
|
||||
if File.exists? "../Cartfile"
|
||||
use_rome = File.exists? "../Romefile"
|
||||
|
||||
swift_version = sh("xcrun swift --version | head -1 | sed 's/.*\\(\(.*\)\\).*/\\1/' | tr -d \"()\" | tr \" \" \"-\"").chop
|
||||
rome_path = "Pods/Rome/rome"
|
||||
rome_options = "--platform iOS --cache-prefix #{swift_version} --romefile Romefile"
|
||||
|
||||
carthage_install = lambda do
|
||||
if use_rome
|
||||
sh("cd .. && #{rome_path} download #{rome_options}")
|
||||
end
|
||||
|
||||
carthage(command: "bootstrap", platform: "iOS", cache_builds: true)
|
||||
|
||||
if use_rome
|
||||
sh("cd .. && #{rome_path} list --missing #{rome_options} | awk '{print $1}' | xargs -I framework_name #{rome_path} upload framework_name #{rome_options}")
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
carthage_install.call
|
||||
rescue
|
||||
# workaround for https://github.com/Carthage/Carthage/issues/2298
|
||||
sh("rm -rf ~/Library/Caches/org.carthage.CarthageKit")
|
||||
carthage_install.call
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private_lane :uploadToFirebase do |options|
|
||||
releaseNotesFile = "release-notes.txt"
|
||||
sh("touch ../#{releaseNotesFile}")
|
||||
|
||||
sh("yarn install")
|
||||
|
||||
app_target_folder_name = options[:appName] || $appName
|
||||
configuration_type = Touchlane::ConfigurationType.from_type(options[:type])
|
||||
|
||||
|
|
@ -73,8 +48,7 @@ private_lane :uploadToFirebase do |options|
|
|||
app: google_app_id,
|
||||
ipa_path: options[:ipa_path],
|
||||
groups: "touch-instinct",
|
||||
release_notes_file: releaseNotesFile,
|
||||
firebase_cli_path: File.expand_path("../node_modules/firebase-tools/lib/bin/firebase.js")
|
||||
release_notes_file: releaseNotesFile
|
||||
)
|
||||
|
||||
upload_symbols_to_crashlytics(
|
||||
|
|
@ -97,7 +71,7 @@ end
|
|||
|
||||
private_lane :addShield do |options|
|
||||
buildNumber = options[:buildNumber]
|
||||
buildDescription = options[:xcconfig_name] # EnterpriseCustomerDev1WithoutSSLPinningRelease
|
||||
buildDescription = options[:lane_name] # EnterpriseCustomerDev1WithoutSSLPinningRelease
|
||||
.split(/(?=[A-Z])/) # -> ["Enterprise", "Customer", "Dev1", "Without", "S", "S", "L", "Pinning", "Release"]
|
||||
.map { |v| v.gsub(/[[:lower:]]+/, "") }[1..2] # -> ["E", "C", "D1", "W", "S", "S", "L", "P", "R"] -> ["C", "D1"]
|
||||
.join # -> "CD1"
|
||||
|
|
@ -113,36 +87,42 @@ private_lane :addShield do |options|
|
|||
end
|
||||
|
||||
private_lane :buildConfiguration do |options|
|
||||
appName = options[:appName] || $appName
|
||||
options[:appName] = options[:appName] || $appName
|
||||
|
||||
lane_name = lane_context[SharedValues::LANE_NAME]
|
||||
lane_name = options[:lane_name] || lane_context[SharedValues::LANE_NAME]
|
||||
|
||||
options[:scheme] = appName
|
||||
options[:xcconfig_name] = lane_name
|
||||
options[:scheme] = options[:scheme] || options[:appName]
|
||||
options[:lane_name] = lane_name
|
||||
|
||||
ipa_name = "#{options[:appName]}.ipa"
|
||||
options[:output_name] = ipa_name
|
||||
|
||||
options[:ipa_path] = "./#{ipa_name}"
|
||||
options[:dsym_path] = "./#{options[:appName]}.app.dSYM.zip"
|
||||
|
||||
options[:xcodeproj_path] = options[:xcodeproj_path] || "../#{options[:appName]}.xcodeproj"
|
||||
options[:workspace] = options[:workspace] || File.expand_path("../#{options[:appName]}.xcworkspace")
|
||||
|
||||
configuration_type = Touchlane::ConfigurationType.from_lane_name(lane_name)
|
||||
options = fill_up_options_using_configuration_type(options, configuration_type)
|
||||
|
||||
generate_xcodeproj_if_needed(options)
|
||||
|
||||
openKeychain(options)
|
||||
|
||||
if is_ci
|
||||
increment_build_number_in_xcodeproj(
|
||||
build_number: options[:buildNumber],
|
||||
xcodeproj: "./#{appName}.xcodeproj"
|
||||
xcodeproj: "./#{options[:appName]}.xcodeproj",
|
||||
target: options[:appName]
|
||||
)
|
||||
end
|
||||
|
||||
ipa_name = "#{appName}.ipa"
|
||||
options[:output_name] = ipa_name
|
||||
|
||||
options[:ipa_path] = "./#{ipa_name}"
|
||||
options[:dsym_path] = "./#{appName}.app.dSYM.zip"
|
||||
|
||||
options[:xcodeproj_path] = "../#{appName}.xcodeproj"
|
||||
options[:workspace] = "./#{appName}.xcworkspace"
|
||||
|
||||
installDependencies(options)
|
||||
|
||||
run_code_generation_phase_if_needed(options)
|
||||
generate_enabled_features_extension_if_needed(options)
|
||||
|
||||
if !(options[:uploadToFabric] || options[:uploadToAppStore])
|
||||
options[:skip_package_ipa] = true
|
||||
|
||||
|
|
@ -171,16 +151,33 @@ private_lane :buildConfiguration do |options|
|
|||
end
|
||||
|
||||
private_lane :buildArchive do |options|
|
||||
|
||||
require 'json'
|
||||
|
||||
icloudEnvironment = options[:iCloudContainerEnvironment] || ""
|
||||
exportOptions = icloudEnvironment.to_s.empty? ? {} : {iCloudContainerEnvironment: icloudEnvironment}
|
||||
exportOptions[:compileBitcode] = options[:compileBitcode] || false
|
||||
|
||||
xcconfig_name = options[:xcconfig_name]
|
||||
lane_name = options[:lane_name]
|
||||
configuration = options[:configuration]
|
||||
xcodeproj_path = options[:xcodeproj_path]
|
||||
xcode_version = options[:xcodeVersion]
|
||||
|
||||
cmd = 'system_profiler -json SPDeveloperToolsDataType'
|
||||
cmd_result = `#{cmd}`
|
||||
spdeveloperToolsDataType = JSON.parse(cmd_result)['SPDeveloperToolsDataType']
|
||||
sortedSPDeveloperToolsDataType = spdeveloperToolsDataType.sort_by { |hash| hash['spdevtools_version'].split(' ').first.to_i } # sort by increasing the version of xcode
|
||||
default_xcode_version = sortedSPDeveloperToolsDataType.last['spdevtools_version'] # take the largest version in format: "13.0 (13A5212g)"
|
||||
default_xcode_version_number = default_xcode_version.split(' ').first # take version number
|
||||
|
||||
if configuration != "AppStore" # AppStore uses xcconfig choosen in Xcode
|
||||
set_xcconfig_for_configuration_of_project(xcconfig_name, configuration, xcodeproj_path)
|
||||
set_xcconfig_for_configuration_of_project(lane_name, configuration, xcodeproj_path)
|
||||
end
|
||||
|
||||
if xcode_version.nil?
|
||||
xcversion(version: default_xcode_version_number)
|
||||
else
|
||||
xcversion(version: xcode_version)
|
||||
end
|
||||
|
||||
gym(
|
||||
|
|
@ -450,7 +447,8 @@ def set_xcconfig_for_configuration_of_project(lane_name, configuration, xcodepro
|
|||
target_to_modify_selector = lambda do |t|
|
||||
supported_product_types = [
|
||||
Xcodeproj::Constants::PRODUCT_TYPE_UTI[:application],
|
||||
Xcodeproj::Constants::PRODUCT_TYPE_UTI[:app_extension]
|
||||
Xcodeproj::Constants::PRODUCT_TYPE_UTI[:app_extension],
|
||||
Xcodeproj::Constants::PRODUCT_TYPE_UTI[:framework]
|
||||
]
|
||||
return !t.test_target_type? && supported_product_types.include?(t.product_type)
|
||||
end
|
||||
|
|
@ -461,9 +459,33 @@ def set_xcconfig_for_configuration_of_project(lane_name, configuration, xcodepro
|
|||
build_configuration = target.build_configuration_list[configuration]
|
||||
config_name = target.name + lane_name
|
||||
build_configuration_reference = project.files.select { |f| f.path.start_with?(config_name) }.first
|
||||
build_configuration.base_configuration_reference = build_configuration_reference
|
||||
|
||||
if !build_configuration_reference.nil? # target has custom xcconfig
|
||||
build_configuration = target.build_configuration_list[configuration]
|
||||
build_configuration.base_configuration_reference = build_configuration_reference
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
project.save()
|
||||
end
|
||||
|
||||
def generate_xcodeproj_if_needed(options)
|
||||
project_yml_path = File.expand_path "../project.yml"
|
||||
|
||||
if !File.exists?(options[:xcodeproj_path]) && File.exists?(project_yml_path)
|
||||
xcodegen(
|
||||
spec: project_yml_path
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# Build phases
|
||||
|
||||
def run_code_generation_phase_if_needed(options)
|
||||
code_generation_script_path = File.expand_path "../.githooks/scripts/CodeGen.sh"
|
||||
|
||||
if File.exists? code_generation_script_path
|
||||
sh(code_generation_script_path, options[:workspace])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -64,39 +64,12 @@ def fetch_development_team(development_team_key, distribution_type)
|
|||
return config_option(development_team_key, team_value)
|
||||
end
|
||||
|
||||
# Return empty array or generated provisioning profile hash
|
||||
def generate_provisioning_profile(provisioning_key, bundle_id, distribution_type)
|
||||
case distribution_type
|
||||
when "appstore"
|
||||
app_store_profile = "match AppStore " + bundle_id
|
||||
config_option(provisioning_key, app_store_profile)
|
||||
else
|
||||
config_option(provisioning_key, bundle_id)
|
||||
end
|
||||
end
|
||||
|
||||
def generate_google_service_info_plist_path(google_service_info_plist_key, target_name, distribution_type)
|
||||
google_service_info_plist_path = target_name + "/Resources/"
|
||||
|
||||
path_suffix = case distribution_type
|
||||
when "development"
|
||||
"Standard-GoogleService-Info.plist"
|
||||
when "enterprise"
|
||||
"Enterprise-GoogleService-Info.plist"
|
||||
else
|
||||
"AppStore-GoogleService-Info.plist"
|
||||
end
|
||||
|
||||
return config_option(google_service_info_plist_key, google_service_info_plist_path + path_suffix)
|
||||
end
|
||||
|
||||
# Generate missing properties if needed
|
||||
def generate_missing_properties(target_name, properties, distribution_type)
|
||||
result = []
|
||||
development_team_key = "DEVELOPMENT_TEAM"
|
||||
provisioning_key = "PROVISIONING_PROFILE_SPECIFIER"
|
||||
google_service_info_plist_key = "GOOGLE_SERVICE_INFO_PLIST_PATH"
|
||||
bundle_id_key = "PRODUCT_BUNDLE_IDENTIFIER"
|
||||
code_sign_style_key = "CODE_SIGN_STYLE"
|
||||
|
||||
# Bundle_id_key should be among the properties (required by fastlane)
|
||||
unless properties.key?(bundle_id_key)
|
||||
|
|
@ -107,12 +80,8 @@ def generate_missing_properties(target_name, properties, distribution_type)
|
|||
result.append(fetch_development_team(development_team_key, distribution_type))
|
||||
end
|
||||
|
||||
unless properties.key?(provisioning_key)
|
||||
result.append(generate_provisioning_profile(provisioning_key, properties[bundle_id_key], distribution_type))
|
||||
end
|
||||
|
||||
unless properties.key?(google_service_info_plist_key)
|
||||
result.append(generate_google_service_info_plist_path(google_service_info_plist_key, target_name, distribution_type))
|
||||
unless properties.key?(code_sign_style_key)
|
||||
result.append(config_option(code_sign_style_key, "Manual"))
|
||||
end
|
||||
|
||||
return result
|
||||
|
|
@ -133,7 +102,11 @@ targets.each do |target_name, target|
|
|||
|
||||
# Add properties from settings file
|
||||
properties.each do |key, value|
|
||||
config["xcconfig_options"].append(config_option(key, value))
|
||||
if config["xcconfig_options"].any? { |option| key == option["key"] }
|
||||
config["xcconfig_options"].map! { |option| key == option["key"] ? config_option(key, value) : option }
|
||||
else
|
||||
config["xcconfig_options"].append(config_option(key, value))
|
||||
end
|
||||
end
|
||||
|
||||
# Add missing properties if needed
|
||||
|
|
|
|||
|
|
@ -2,6 +2,4 @@
|
|||
|
||||
{{#configuration.xcconfig_options}}
|
||||
{{key}} = {{value}}
|
||||
{{/configuration.xcconfig_options}}
|
||||
|
||||
CODE_SIGN_STYLE = Manual
|
||||
{{/configuration.xcconfig_options}}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
module Touchlane
|
||||
require_relative "touchlane/configuration_type"
|
||||
require_relative "touchlane/configuration"
|
||||
require_relative "touchlane/features"
|
||||
require_relative "match/storage/local_storage"
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
require_relative '../../../../managers/managers'
|
||||
require_relative '../../../../templates/templates'
|
||||
|
||||
module Touchlane
|
||||
class Features
|
||||
|
||||
def self.generate_enabled_features_extension(builder_features_list, build_settings_features_list)
|
||||
|
||||
# Check is entered features contains in configuration file
|
||||
features_diff = builder_features_list - build_settings_features_list
|
||||
|
||||
unless features_diff.empty?
|
||||
raise "Unexpected features: " + features_diff.join(', ')
|
||||
end
|
||||
|
||||
# Generate enabled features extension from feature names
|
||||
enabled_features_extension_template = Templates::FeatureTemplates.enabled_features_extension
|
||||
utils = Managers::TemplateManager.new(builder_features_list)
|
||||
|
||||
utils.render(enabled_features_extension_template).strip
|
||||
end
|
||||
|
||||
private_class_method :new
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
require 'yaml'
|
||||
require 'json'
|
||||
|
||||
module Managers
|
||||
class FileManager
|
||||
|
||||
def self.save_data_to_file(path, data)
|
||||
unless File.exists? path
|
||||
raise "Unable to save data to file at #{path}"
|
||||
else
|
||||
File.open(path, "w") do |f|
|
||||
f.write(data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.load_from_file_YAML(path)
|
||||
unless File.exists? path
|
||||
raise "Unable to load data from file at #{path}"
|
||||
else
|
||||
YAML.load_file(path)
|
||||
end
|
||||
end
|
||||
|
||||
def self.save_data_to_file_in_json(path, data)
|
||||
json_data = JSON.pretty_generate(data)
|
||||
save_data_to_file(path, json_data)
|
||||
end
|
||||
|
||||
private_class_method :new
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
require 'erb'
|
||||
|
||||
module Managers
|
||||
class TemplateManager
|
||||
|
||||
include ERB::Util
|
||||
|
||||
attr_accessor :items
|
||||
|
||||
def initialize(items)
|
||||
@items = items
|
||||
end
|
||||
|
||||
def render(template)
|
||||
ERB.new(template).result(binding)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
module Managers
|
||||
require_relative "lib/file_manager"
|
||||
require_relative "lib/template_manager"
|
||||
end
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
module Templates
|
||||
require_relative "templates/features_templates"
|
||||
end
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
module Templates
|
||||
module FeatureTemplates
|
||||
|
||||
def self.features_enum
|
||||
"
|
||||
// MARK: - Generated feature toggles
|
||||
|
||||
public enum Feature: String, Codable, RawRepresentable, CaseIterable {
|
||||
<% for @item in @items %>
|
||||
case <%= @item %>
|
||||
<% end %>
|
||||
}
|
||||
"
|
||||
end
|
||||
|
||||
def self.enabled_features_extension
|
||||
"
|
||||
// MARK: - Generated enabled features
|
||||
|
||||
public extension Feature {
|
||||
|
||||
static var enabled: [Feature] {
|
||||
[
|
||||
<% for @item in @items %>
|
||||
\.<%= @item %>,
|
||||
<% end %>
|
||||
]
|
||||
}
|
||||
}
|
||||
"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue