Skip to content
This repository has been archived by the owner on Jun 3, 2021. It is now read-only.

Add Lint in TravisCI and Update iOS TravisCI #2731

Merged
merged 143 commits into from
Aug 8, 2019

Conversation

wrmswindmill
Copy link
Contributor

@wrmswindmill wrmswindmill commented Jul 19, 2019

Brief Description of the PR

Add Static Check in Travis CI

Lint Tool Lists:

  1. oclint : for c,c++,objective-c
  2. android lint:for android project

Check FileType

const getFileType = file => {
  if (file.match(/.+\.(m|h|mm|cpp|cc)/)) {
    return type_c;
  } else if (file.match(/.+\.java/)) {
    return type_android;
  }else{
    return type_unknown;
  }
}

OCLint in .travis.yml

- env: STATIC_CODE_ANALYSIS=true CHECK_C=true
     language: objective-c
     osx_image: xcode7.2

before_install:
  - |
    # install oclint
    if [[ ("${STATIC_CODE_ANALYSIS}" = "true") && ("${CHECK_C}" = "true") ]]; then
      brew cask uninstall oclint
      brew tap oclint/formulae
      brew install oclint
    fi

install:
   elif [[ ("$TEST_SUITE" = "jsfm") || ("$TEST_SUITE" = "danger") ||  ("${CHECK_C}" = "true") ]]; then
        npm install
    ;;

script:
if [[ ("${STATIC_CODE_ANALYSIS}" = "true") && ("${CHECK_C}" = "true") ]]; then
      hasCFile=$(npm run danger -- run --dangerfile ./dangerfile-static-check.js)
      echo "The value of hasCFile is ${hasCFile}"
      if [[ "$hasCFile" =~ "hasCFile" ]]; then
        echo "hasCFile"
        cd ios/sdk && xcodebuild | xcpretty -r json-compilation-database -o compile_commands.json
        oclint-json-compilation-database oclint_args -- \
          -disable-rule=ShortVariableName \
          -disable-rule=LongLine \
          -disable-rule=LongMethod \
          -disable-rule=HighNcssMethod \
          -disable-rule=LongVariableName \
          -disable-rule=HighCyclomaticComplexity \
          -disable-rule=HighNPathComplexity \
          -disable-rule=UnusedLocalVariable \
          -disable-rule=DoubleNegative \
          -disable-rule=MultipleUnaryOperator \
          -disable-rule=DeepNestedBlock \
          -max-priority-1=15000 \
          -max-priority-2=15000 \
          -max-priority-3=15000
      fi
    fi 

Android Lint in .travis.yml

- env: STATIC_CODE_ANALYSIS=true CHECK_ANDROID=true
     language: android
     dist: trusty
     jdk: oraclejdk8
     android:
       components:
          - android-26
          - extra-android-m2repository

install:
if [[ ("$TEST_SUITE" = "android") || ("${CHECK_ANDROID}" = "true") ]]; then
        curl -o- https://github.com/raw/nvm-sh/nvm/v0.34.0/install.sh | bash
        nvm install 7.6
        npm install
        echo y | sdkmanager "cmake;3.6.4111459"
        if find "${HOME}/android-ndk-r18b" -mindepth 1 | read; then
          echo "NDK cache hit"
        else
          echo "NDK cache missed"
          rmdir "${HOME}/android-ndk-r18b"
        fi

        if [[ ! -d "${HOME}/android-ndk-r18b" ]]; then
          wget https://dl.google.com/android/repository/android-ndk-r18b-linux-x86_64.zip
          unzip android-ndk-r18b-linux-x86_64.zip -d $HOME
        fi
        export ANDROID_NDK_HOME=$HOME/android-ndk-r18b
        export PATH=$PATH:$ANDROID_NDK_HOME
        echo "ndk.dir=$ANDROID_NDK_HOME" > android/local.properties

script:
if [[ ("${STATIC_CODE_ANALYSIS}" = "true") && ("${CHECK_ANDROID}" = "true") ]]; then
      hasAndroidFile=$(npm run danger -- run --dangerfile ./dangerfile-static-check.js)
      echo "The value of hasAndroidFile is ${hasAndroidFile}"
      if [[ "$hasAndroidFile" =~ "hasAndroidFile" ]]; then
        echo "hasAndroidFile"
        cd android
        ./gradlew lint
      fi
    fi

Code Format

code format with danger-code_style_validation based on clang-format
clang-format support code format for program language like:java, c++, c, objective.

  1. create a new file named Dangerfile and add a new line:
code_style_validation.check file_extensions: ['.cc', '.cpp', '.m', 'mm', '.h', '.java'] 
  1. add a new line in Gemfile
gem 'danger-code_style_validation', :git => 'https://github.com/wrmswindmill/danger-code_style_validation.git'
  1. update Travis.yml
matrix:
    fast_finish: true
    include:
      # format code using clang-format
      - env: FORMAT_CODE=true
        language: ruby

install:
    elif [[ ("${FORMAT_CODE}" = "true" )]]; then
        bundle install
    fi

script:
    if [[ ("${FORMAT_CODE}" = "true" )]]; then
        echo "exec danger ruby"
        bundle exec danger
    fi

Update iOS

install:
  elif [[ ("$TEST_SUITE" = "ios") ]]; then
        git submodule update --init --remote
        cd weex-playground/ios && bash update_podfile_for_travisci.sh
        cd ../../ && npm install
        cd weex-playground/ios && pod install --repo-update
        cd ../../
  fi
script:
   "ios" )
        hasIosFile=$(npm run danger -- run --dangerfile ./dangerfile-ios.js)
        echo "The value of hasIosFile is ${hasIosFile}"
        if [[ "$hasIosFile" =~ "hasIosFile" ]]; then
          # build WeexSDK and run WeexSDKTests
          xcodebuild -project ios/sdk/WeexSDK.xcodeproj test -scheme WeexSDKTests CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO -destination "platform=iOS Simulator,name=iPhone 6" || exit 1
          # build WeexDemo and run WeexDemo test
          cd weex-playground/ios && mkdir tmp && mv * tmp;cd tmp
          xcodebuild -workspace WeexDemo.xcworkspace test -scheme WeexDemo CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO -destination "platform=iOS Simulator,name=iPhone 6" || exit 1
        fi
        ;;

Todo

  • Discuss OCLint Rules
  • Discuss Android Rules

Links

  1. OCLint Rules:http://docs.oclint.org/en/stable/rules/index.html

@weex-bot
Copy link

weex-bot commented Jul 31, 2019

Warnings
⚠️ These new JS files do not have Flow enabled: dangerfile-output.js, dangerfile-static-check.js
⚠️ No Changelog changes! - Can you add a Changelog? To do so,append your changes to the changelog.md
⚠️ If your PR is about fixing a bug excluding crash the code,you should add the demo link in the PR description. Demo link: http://dotwe.org/vue
Messages
📖 danger test finished.

Generated by 🚫 dangerJS against 4fbb51e

@weex-bot
Copy link

weex-bot commented Jul 31, 2019

Messages
📖 jsfm test finished.
📖 has no jsfm file changed.

Generated by 🚫 dangerJS against 4fbb51e

@weex-bot
Copy link

weex-bot commented Jul 31, 2019

Fails
🚫 OCLint Result
🚫

Summary: TotalFiles=370 FilesWithViolations=113 P1=0 P2=68 P3=966
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m:86:49: dead code [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.mm:269:12: empty else block [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.mm:938:36: empty if statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Manager/WXServiceFactory.m:44:28: empty if statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m:433:53: constant conditional operator [basic|P2]
/Users/travis/build/apache/incubator-weex/weex_core/Source/third_party/json11/json11.cc:149:1: destructor of virtual class [convention|P2] class Value should have a virtual destructor ~Value()
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.mm:1103:51: empty if statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Display/UIBezierPath+Weex.m:36:8: constant conditional operator [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Display/UIBezierPath+Weex.m:36:32: constant conditional operator [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Display/UIBezierPath+Weex.m:36:57: constant conditional operator [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Display/UIBezierPath+Weex.m:36:84: constant conditional operator [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Display/UIBezierPath+Weex.m:39:50: constant conditional operator [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Display/UIBezierPath+Weex.m:39:77: constant conditional operator [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXWebComponent.m:37:15: empty if statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXTransform.m:180:56: constant conditional operator [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXSliderNeighborComponent.mm:1624:5: empty do/while statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXSliderNeighborComponent.mm:96:16: empty if statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXVideoComponent.m:298:17: empty do/while statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXVideoComponent.m:84:34: empty if statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.mm:249:58: constant if expression [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.mm:250:50: constant if expression [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.mm:251:62: constant if expression [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.mm:252:59: constant if expression [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.mm:253:50: constant if expression [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.mm:254:63: constant if expression [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.mm:255:74: constant if expression [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.mm:256:62: constant if expression [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.mm:257:54: constant if expression [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.mm:258:60: constant if expression [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.mm:259:54: constant if expression [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.m:293:13: dead code [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m:706:29: empty catch statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m:993:16: empty else block [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.mm:201:52: empty if statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m:1064:37: empty catch statement [empty|P2]
/Users/travis/build/apache/incubator-weex/weex_core/Source/core/render/manager/render_manager.cpp:457:45: empty if statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXEditComponent.mm:678:145: empty if statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Module/WXStorageModule.m:463:5: empty do/while statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.mm:733:53: empty if statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.mm:735:57: empty if statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.mm:756:57: empty if statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXListComponent.mm:979:33: empty catch statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXListComponent.mm:997:33: empty catch statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXListComponent.mm:1019:38: empty catch statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXListComponent.mm:1041:35: empty catch statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXListComponent.mm:403:28: empty finally statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXListComponent.mm:659:27: empty finally statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m:913:41: dead code [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m:409:20: empty finally statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m:492:15: empty finally statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m:555:19: empty finally statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m:715:19: empty finally statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m:111:15: empty if statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm:167:9: constant conditional operator [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm:399:9: constant conditional operator [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm:1041:9: constant conditional operator [basic|P2]
/Users/travis/build/apache/incubator-weex/weex_core/Source/wson/wson_parser.cpp:234:13: dead code [basic|P2]
/Users/travis/build/apache/incubator-weex/weex_core/Source/wson/wson_parser.cpp:154:5: missing break in switch statement [convention|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/WXCycleSliderComponent.mm:649:5: empty do/while statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Module/WXModalUIModule.m:83:30: empty if statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m:394:14: constant conditional operator [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m:394:35: constant conditional operator [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m:521:25: constant conditional operator [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m:839:20: empty finally statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m:138:16: empty else block [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/Recycler/WXMultiColumnLayout.m:193:20: empty finally statement [empty|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.mm:878:9: constant conditional operator [basic|P2]
/Users/travis/build/apache/incubator-weex/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.mm:290:5: missing break in switch statement [convention|P2]

Generated by 🚫 dangerJS against 4fbb51e

@weex-bot
Copy link

weex-bot commented Jul 31, 2019

Warnings
⚠️ AndroidLint Result
⚠️

Missing Permissions

../../src/main/java/com/taobao/weex/WXEnvironment.java:400: Missing permissions required by TelephonyManager.getDeviceId: android.permission.READ_PHONE_STATE
 397   }
 398 
 399   private static String getDevId() {
 400     return sApplication == null ? "" : ((TelephonyManager) sApplication                             
 401             .getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId();
 402   }
This check scans through your code and libraries and looks at the APIs being used, and checks this against the set of permissions required to access those APIs. If the code using those APIs is called at runtime, then the program will crash.

Furthermore, for permissions that are revocable (with targetSdkVersion 23), client code must also be prepared to handle the calls throwing an exception if the user rejects the request for permission at runtime.
Note: This issue has an associated quickfix operation in Android Studio and IntelliJ IDEA.
To suppress this error, use the issue id "MissingPermission" as explained in the Suppressing Warnings and Errors section.

MissingPermission Correctness Error Priority 9/10
Explain Dismiss

Wrong Canvas Size

../../src/main/java/com/taobao/weex/ui/component/WXComponent.java:1685: Calling Canvas.getHeight() is usually wrong; you should be calling getBounds().getHeight() instead
 1682   @Override
 1683   public void draw(@NonNull Canvas canvas) {
 1684     if (mBackgroundDrawable != null) {
 1685       Path border = mBackgroundDrawable.getContentPath(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()));
 1686       canvas.clipPath(border);
 1687     }
 1688     super.draw(canvas);

../../src/main/java/com/taobao/weex/ui/component/WXComponent.java:1685: Calling Canvas.getWidth() is usually wrong; you should be calling getBounds().getWidth() instead


1682 @Override
1683 public void draw(@NonNull Canvas canvas) {
1684 if (mBackgroundDrawable != null) {
1685 Path border = mBackgroundDrawable.getContentPath(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()));
1686 canvas.clipPath(border);
1687 }
1688 super.draw(canvas);

In a custom view's draw implementation, you should normally call getWidth and getHeight on the custom view itself, not on the canvas instance.

Canvas width and height are the width and height of the Canvas, which is not always the same as size of the view.

In the hardware accelerated path the width and height of the canvas typically always match that of the View because every view goes to its own recorded DisplayList. But in software rendering there's just one canvas that is clipped and transformed as it makes its way through the View tree, and otherwise remains the same Canvas object for every View's draw method.

You should only use Canvas state to adjust how much you draw, such as a quick-reject for early work avoidance if it's going to be clipped away, but not what you draw.
To suppress this error, use the issue id "CanvasSize" as explained in the Suppressing Warnings and Errors section.

CanvasSize Correctness Warning Priority 6/10
Explain Dismiss

Implied default locale in case conversion

../../src/main/java/com/taobao/weex/ui/component/WXComponent.java:983: Implicitly using the default locale is a common source of bugs: Use String.format(Locale, ...) instead
  980   mInstance.getWXPerformance().cellExceedNum++;
  981   if (WXAnalyzerDataTransfer.isOpenPerformance){
  982     WXAnalyzerDataTransfer.transferPerformance(getInstanceId(),"details",WXInstanceApm.KEY_PAGE_STATS_CELL_EXCEED_NUM,
  983         String.format("cell:[w:%d,h:%d],attrs:%s,styles:%s",realWidth,realHeight,getAttrs(),getStyles())
  984     );
  985   }

../../src/main/java/com/taobao/weex/WXEnvironment.java:61: Implicitly using the default locale is a common source of bugs: Use toUpperCase(Locale) instead. For strings meant to be internal use Locale.ROOT, otherwise Locale.getDefault().


58 public static final String OS = "android";
59 public static String SYS_VERSION = android.os.Build.VERSION.RELEASE;
60 static{
61 if(SYS_VERSION != null && SYS_VERSION.toUpperCase().equals("P")){                               
62 SYS_VERSION = "9.0.0";
63 }
64 if(SYS_VERSION != null && SYS_VERSION.toUpperCase().equals("Q")){

../../src/main/java/com/taobao/weex/WXEnvironment.java:64: Implicitly using the default locale is a common source of bugs: Use toUpperCase(Locale) instead. For strings meant to be internal use Locale.ROOT, otherwise Locale.getDefault().


61 if(SYS_VERSION != null && SYS_VERSION.toUpperCase().equals("P")){
62 SYS_VERSION = "9.0.0";
63 }
64 if(SYS_VERSION != null && SYS_VERSION.toUpperCase().equals("Q")){                               
65 SYS_VERSION = "10.0.0";
66 }
67 }

../../src/main/java/com/taobao/weex/ui/component/WXImage.java:487: Implicitly using the default locale is a common source of bugs: Use String.format(Locale, ...) instead


484
485 if (WXAnalyzerDataTransfer.isOpenPerformance){
486 WXAnalyzerDataTransfer.transferPerformance(getInstanceId(),"details",WXInstanceApm.KEY_PAGE_STATS_WRONG_IMG_SIZE_COUNT,
487 String.format("imgSize:[%d,%d],viewSize:[%d,%d],urL:%s",imgWidth,imgHeight,imageView.getMeasuredWidth(),imageView.getMeasuredHeight()
488 ,currentImgUrlStr)
489 );
490 }

../../src/main/java/com/taobao/weex/utils/WXResourceUtils.java:337: Implicitly using the default locale is a common source of bugs: Use toLowerCase(Locale) instead. For strings meant to be internal use Locale.ROOT, otherwise Locale.getDefault().


334 float[] points = {0, 0, 0, 0};
335
336 if (!TextUtils.isEmpty(direction)) {
337 direction = direction.replaceAll("\s*", "").toLowerCase();                                   
338 }
339
340 switch (direction) {

+ 5 More Occurrences...

../../src/main/java/com/taobao/weex/utils/WXSoInstallMgrSdk.java:361: Implicitly using the default locale is a common source of bugs: Use toLowerCase(Locale) instead. For strings meant to be internal use Locale.ROOT, otherwise Locale.getDefault().
 358       if (TextUtils.isEmpty(mAbi)){
 359         mAbi = ARMEABI;
 360       }
 361       mAbi = mAbi.toLowerCase();                                                                    
 362     }
 363     return mAbi;
 364   }

../../src/main/java/com/taobao/weex/http/WXStreamModule.java:79: Implicitly using the default locale is a common source of bugs: Use toUpperCase(Locale) instead. For strings meant to be internal use Locale.ROOT, otherwise Locale.getDefault().


76 String body = paramsObj.getString("body");
77 int timeout = paramsObj.getIntValue("timeout");
78
79 if (method != null) method = method.toUpperCase();                                              
80 Options.Builder builder = new Options.Builder()
81 .setMethod(!"GET".equals(method)
82 &&!"POST".equals(method)

../../src/main/java/com/taobao/weex/http/WXStreamModule.java:160: Implicitly using the default locale is a common source of bugs: Use toUpperCase(Locale) instead. For strings meant to be internal use Locale.ROOT, otherwise Locale.getDefault().


157 }
158 }
159
160 if (method != null) method = method.toUpperCase();                                              
161 Options.Builder builder = new Options.Builder()
162 .setMethod(!"GET".equals(method)
163 &&!"POST".equals(method)

../../src/main/java/com/taobao/weex/http/WXStreamModule.java:237: Implicitly using the default locale is a common source of bugs: Use toLowerCase(Locale) instead. For strings meant to be internal use Locale.ROOT, otherwise Locale.getDefault().


234 if(headers.containsKey(key)){
235 return headers.get(key);
236 }else{
237 return headers.get(key.toLowerCase());                                                        
238 }
239 }

../../src/main/java/com/taobao/weex/http/WXStreamModule.java:246: Implicitly using the default locale is a common source of bugs: Use toLowerCase(Locale) instead. For strings meant to be internal use Locale.ROOT, otherwise Locale.getDefault().


243 static String readAsString(byte[] data,String cType){
244 String charset = "utf-8";
245 if(cType != null){
246 Matcher matcher = CHARSET_PATTERN.matcher(cType.toLowerCase());                               
247 if(matcher.find()){
248 charset = matcher.group(1);
249 }

Calling String#toLowerCase() or #toUpperCase() without specifying an explicit locale is a common source of bugs. The reason for that is that those methods will use the current locale on the user's device, and even though the code appears to work correctly when you are developing the app, it will fail in some locales. For example, in the Turkish locale, the uppercase replacement for i is not I.

If you want the methods to just perform ASCII replacement, for example to convert an enum name, call String#toUpperCase(Locale.US) instead. If you really want to use the current locale, call String#toUpperCase(Locale.getDefault()) instead.
To suppress this error, use the issue id "DefaultLocale" as explained in the Suppressing Warnings and Errors section.

DefaultLocale Correctness Warning Priority 6/10
Explain Dismiss

Using inlined constants on older versions

../../src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java:202: Field requires API level 17 (current min is 14): android.view.View#LAYOUT_DIRECTION_LTR
  199   @Override
  200   public void setLayout(WXComponent component) {
  201     if (component.getHostView() != null) {
  202       int layoutDirection = component.isLayoutRTL() ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
  203       ViewCompat.setLayoutDirection(component.getHostView(), layoutDirection);
  204     }
  205     super.setLayout(component);

../../src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java:202: Field requires API level 17 (current min is 14): android.view.View#LAYOUT_DIRECTION_RTL


199 @Override
200 public void setLayout(WXComponent component) {
201 if (component.getHostView() != null) {
202 int layoutDirection = component.isLayoutRTL() ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
203 ViewCompat.setLayoutDirection(component.getHostView(), layoutDirection);
204 }
205 super.setLayout(component);

../../src/main/java/com/taobao/weex/ui/component/WXScroller.java:422: Field requires API level 17 (current min is 14): android.view.View#LAYOUT_DIRECTION_LTR


419 return;
420 }
421 if (component.getHostView() != null) {
422 int layoutDirection = component.isLayoutRTL() ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
423 ViewCompat.setLayoutDirection(component.getHostView(), layoutDirection);
424 }
425 super.setLayout(component);

../../src/main/java/com/taobao/weex/ui/component/WXScroller.java:422: Field requires API level 17 (current min is 14): android.view.View#LAYOUT_DIRECTION_RTL


419 return;
420 }
421 if (component.getHostView() != null) {
422 int layoutDirection = component.isLayoutRTL() ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
423 ViewCompat.setLayoutDirection(component.getHostView(), layoutDirection);
424 }
425 super.setLayout(component);

This check scans through all the Android API field references in the application and flags certain constants, such as static final integers and Strings, which were introduced in later versions. These will actually be copied into the class files rather than being referenced, which means that the value is available even when running on older devices. In some cases that's fine, and in other cases it can result in a runtime crash or incorrect behavior. It depends on the context, so consider the code carefully and decide whether it's safe and can be suppressed or whether the code needs to be guarded.

If you really want to use this API and don't need to support older devices just set the minSdkVersion in your build.gradle or AndroidManifest.xml files.
If your code is deliberately accessing newer APIs, and you have ensured (e.g. with conditional execution) that this code will only ever be called on a supported platform, then you can annotate your class or method with the @TargetApi annotation specifying the local minimum SDK to apply, such as @TargetApi(11), such that this check considers 11 rather than your manifest file's minimum SDK as the required API level.
Note: This issue has an associated quickfix operation in Android Studio and IntelliJ IDEA.
To suppress this error, use the issue id "InlinedApi" as explained in the Suppressing Warnings and Errors section.

InlinedApi Correctness Warning Priority 6/10
Explain Dismiss

Missing Default

../../src/main/res/values-ldltr/isrtl.xml:23: The bool "weex_is_right_to_left" in values-ldltr has no declaration in the base values folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier
 20 
 21 -->
 22 <resources>
 23     <bool name="weex_is_right_to_left">false</bool>                                                 
 24 </resources>

../../src/main/res/values-ldrtl/istrtl.xml:23: The bool "weex_is_right_to_left" in values-ldrtl has no declaration in the base values folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier


20
21 -->
22 <resources>
23 <bool name="weex_is_right_to_left">true</bool>                                                  
24 </resources>

If a resource is only defined in folders with qualifiers like -land or -en, and there is no default declaration in the base folder (layout or values etc), then the app will crash if that resource is accessed on a device where the device is in a configuration missing the given qualifier.

As a special case, drawables do not have to be specified in the base folder; if there is a match in a density folder (such as drawable-mdpi) that image will be used and scaled. Note however that if you only specify a drawable in a folder like drawable-en-hdpi, the app will crash in non-English locales.

There may be scenarios where you have a resource, such as a -fr drawable, which is only referenced from some other resource with the same qualifiers (such as a -fr style), which itself has safe fallbacks. However, this still makes it possible for somebody to accidentally reference the drawable and crash, so it is safer to create a default dummy fallback in the base folder. Alternatively, you can suppress the issue by adding tools:ignore="MissingDefaultResource" on the element.

(This scenario frequently happens with string translations, where you might delete code and the corresponding resources, but forget to delete a translation. There is a dedicated issue id for that scenario, with the id ExtraTranslation.)
To suppress this error, use the issue id "MissingDefaultResource" as explained in the Suppressing Warnings and Errors section.

MissingDefaultResource Correctness Fatal Priority 6/10
Explain Dismiss

Calling new methods on older versions

../../src/main/java/com/taobao/weex/render/WXAbstractRenderContainer.java:50: Call requires API level 21 (current min is 14): new android.widget.FrameLayout
 47   }
 48 
 49   public WXAbstractRenderContainer(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
 50       super(context, attrs, defStyleAttr, defStyleRes);                                           
 51   }
 52 
 53   public void setSDKInstance(WXSDKInstance instance) {
This check scans through all the Android API calls in the application and warns about any calls that are not available on all versions targeted by this application (according to its minimum SDK attribute in the manifest).

If you really want to use this API and don't need to support older devices just set the minSdkVersion in your build.gradle or AndroidManifest.xml files.

If your code is deliberately accessing newer APIs, and you have ensured (e.g. with conditional execution) that this code will only ever be called on a supported platform, then you can annotate your class or method with the @TargetApi annotation specifying the local minimum SDK to apply, such as @TargetApi(11), such that this check considers 11 rather than your manifest file's minimum SDK as the required API level.

If you are deliberately setting android: attributes in style definitions, make sure you place this in a values-vNN folder in order to avoid running into runtime conflicts on certain devices where manufacturers have added custom attributes whose ids conflict with the new ones on later platforms.

Similarly, you can use tools:targetApi="11" in an XML file to indicate that the element will only be inflated in an adequate context.
Note: This issue has an associated quickfix operation in Android Studio and IntelliJ IDEA.
To suppress this error, use the issue id "NewApi" as explained in the Suppressing Warnings and Errors section.

NewApi Correctness Error Priority 6/10
Explain Dismiss

Hardcoded reference to /sdcard

../../src/main/java/com/taobao/weex/WXEnvironment.java:297: Do not hardcode "/data/"; use Context.getFilesDir().getPath() instead
 294           desDir = new File(cachePath, dirName);
 295         } else {
 296           String pkgName = sApplication.getPackageName();
 297           String toPath = "/data/data/" + pkgName + dirName;                                        
 298           desDir = new File(toPath);
 299         }

../../src/main/java/com/taobao/weex/utils/WXSoInstallMgrSdk.java:257: Do not hardcode "/data/"; use Context.getFilesDir().getPath() instead


254 return;
255 }
256
257 String path = "/data/data/" + pkgName + "/lib";                                               
258 if (cacheFile != null && cacheFile.indexOf("/cache") > 0) {
259 path = cacheFile.replace("/cache", "/lib");
260 }

../../src/main/java/com/taobao/weex/utils/WXSoInstallMgrSdk.java:418: Do not hardcode "/data/"; use Context.getFilesDir().getPath() instead


415 return "";
416 }
417
418 String path = "/data/data/" + context.getPackageName() + "/files";                              
419
420 File f = context.getFilesDir();
421 if (f != null) {

Your code should not reference the /sdcard path directly; instead use Environment.getExternalStorageDirectory().getPath().

Similarly, do not reference the /data/data/ path directly; it can vary in multi-user scenarios. Instead, use Context.getFilesDir().getPath().
To suppress this error, use the issue id "SdCardPath" as explained in the Suppressing Warnings and Errors section.

SdCardPath Correctness Warning Priority 6/10
Explain Dismiss

Toast created but not shown

../../src/main/java/com/taobao/weex/ui/module/WXModalUIModule.java:90: Toast created but not shown: did you forget to call show() ?
  87       duration = Toast.LENGTH_SHORT;
  88     }
  89     if (toast == null) {
  90       toast = Toast.makeText(mWXSDKInstance.getContext(), message, duration);                       
  91     } else {
  92       toast.setDuration(duration);
  93       toast.setText(message);
Toast.makeText() creates a Toast but does not show it. You must call show() on the resulting object to actually make the Toast appear.
To suppress this error, use the issue id "ShowToast" as explained in the Suppressing Warnings and Errors section.

ShowToast Correctness Warning Priority 6/10
Explain Dismiss

Implied locale in date format

../../src/main/java/com/taobao/weex/bridge/WXBridgeManager.java:949: To get local formatting use getDateInstance(), getDateTimeInstance(), or getTimeInstance(), or use new SimpleDateFormat(String template, Locale locale) with for example Locale.US for ASCII dates.
  946   public void callReportCrash(String crashFile, final String instanceId, final String url) {
  947     // statistic weex core process crash
  948     Date date = new Date();
  949     DateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");                                     
  950     String time = format.format(date);
  951     final String origin_filename = crashFile + "." + time;
  952     File oldfile = new File(crashFile);
Almost all callers should use getDateInstance(), getDateTimeInstance(), or getTimeInstance() to get a ready-made instance of SimpleDateFormat suitable for the user's locale. The main reason you'd create an instance this class directly is because you need to format/parse a specific machine-readable format, in which case you almost certainly want to explicitly ask for US to ensure that you get ASCII digits (rather than, say, Arabic digits).

Therefore, you should either use the form of the SimpleDateFormat constructor where you pass in an explicit locale, such as Locale.US, or use one of the get instance methods, or suppress this error if really know what you are doing.
To suppress this error, use the issue id "SimpleDateFormat" as explained in the Suppressing Warnings and Errors section.

SimpleDateFormat Correctness Warning Priority 6/10
Explain Dismiss

Appcompat Custom Widgets

../../src/main/java/com/taobao/weex/ui/view/refresh/circlebar/CircleProgressBar.java:38: This custom view should extend android.support.v7.widget.AppCompatImageView instead
  35 /**
  36  * Modify of android.support.v4
  37  */
  38 public class CircleProgressBar extends ImageView {                                                  
  39 
  40   private static final int KEY_SHADOW_COLOR = 0x1E000000;
  41   private static final int FILL_SHADOW_COLOR = 0x3D000000;

../../src/main/java/com/taobao/weex/ui/view/WXEditText.java:36: This custom view should extend android.support.v7.widget.AppCompatEditText instead


33 /**
34 * Wrapper class for editText
35 */
36 public class WXEditText extends EditText implements WXGestureObservable {                           
37
38 private WXGesture wxGesture;
39 private int mLines = 1;

../../src/main/java/com/taobao/weex/ui/view/WXImageView.java:42: This custom view should extend android.support.v7.widget.AppCompatImageView instead


39 import java.lang.ref.WeakReference;
40 import java.util.Arrays;
41
42 public class WXImageView extends ImageView implements WXGestureObservable,                          
43 IRenderStatus<WXImage>,
44 IRenderResult<WXImage>, WXImage.Measurable {

In order to support features such as tinting, the appcompat library will automatically load special appcompat replacements for the builtin widgets. However, this does not work for your own custom views.

Instead of extending the android.widget classes directly, you should instead extend one of the delegate classes in android.support.v7.widget.AppCompat.
Note: This issue has an associated quickfix operation in Android Studio and IntelliJ IDEA.
To suppress this error, use the issue id "AppCompatCustomView" as explained in the Suppressing Warnings and Errors section.

AppCompatCustomView Correctness Error Priority 4/10
Explain Dismiss

Value overridden by Gradle build script

../../src/main/AndroidManifest.xml:22: This versionCode value (1) is not used; it is always overridden by the value specified in the Gradle build script (1)
 19 -->
 20 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 21           package="com.taobao.weex"
 22           android:versionCode="1"                                                                   
 23           android:versionName="1.0">
 24 
 25     <application>

../../src/main/AndroidManifest.xml:23: This versionName value (1.0) is not used; it is always overridden by the value specified in the Gradle build script (0.26.0.1)


20 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
21 package="com.taobao.weex"
22 android:versionCode="1"
23 android:versionName="1.0">                                                                
24
25 <application>
26 <receiver

The value of (for example) minSdkVersion is only used if it is not specified in the build.gradle build scripts. When specified in the Gradle build scripts, the manifest value is ignored and can be misleading, so should be removed to avoid ambiguity.
To suppress this error, use the issue id "GradleOverrides" as explained in the Suppressing Warnings and Errors section.

GradleOverrides Correctness Warning Priority 4/10
Explain Dismiss

addJavascriptInterface Called

../../src/main/java/com/taobao/weex/ui/view/WXWebView.java:318: WebView.addJavascriptInterface should not be called with minSdkVersion < 17 for security reasons: JavaScript can use reflection to manipulate application
 315             }
 316         });
 317         if (!DOWNGRADE_JS_INTERFACE) {
 318             wv.addJavascriptInterface(new Object() {                                                
 319                 @JavascriptInterface
 320                 public void postMessage(String message, String targetOrigin) {
 321                     onMessage(message, targetOrigin);
For applications built for API levels below 17, WebView#addJavascriptInterface presents a security hazard as JavaScript on the target web page has the ability to use reflection to access the injected object's public fields and thus manipulate the host application in unintended ways.
To suppress this error, use the issue id "AddJavascriptInterface" as explained in the Suppressing Warnings and Errors section.

AddJavascriptInterface Security Warning Priority 9/10
Explain Dismiss

Hardware Id Usage

../../src/main/java/com/taobao/weex/WXEnvironment.java:400: Using getDeviceId to get device identifiers is not recommended.
 397   }
 398 
 399   private static String getDevId() {
 400     return sApplication == null ? "" : ((TelephonyManager) sApplication                             
 401             .getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId();
 402   }
Using these device identifiers is not recommended other than for high value fraud prevention and advanced telephony use-cases. For advertising use-cases, use AdvertisingIdClient$Info#getId and for analytics, use InstanceId#getId.
To suppress this error, use the issue id "HardwareIds" as explained in the Suppressing Warnings and Errors section.

HardwareIds Security Warning Priority 6/10
Explain Dismiss

Using setJavaScriptEnabled

../../src/main/java/com/taobao/weex/ui/view/WXWebView.java:215: Using setJavaScriptEnabled can introduce XSS vulnerabilities into your application, review carefully.
 212 
 213     private void initWebView(WebView wv) {
 214         WebSettings settings = wv.getSettings();
 215         settings.setJavaScriptEnabled(true);                                                        
 216         settings.setAppCacheEnabled(true);
 217         settings.setUseWideViewPort(true);
 218         settings.setDomStorageEnabled(true);
Your code should not invoke setJavaScriptEnabled if you are not sure that your app really requires JavaScript support.
To suppress this error, use the issue id "SetJavaScriptEnabled" as explained in the Suppressing Warnings and Errors section.

SetJavaScriptEnabled Security Warning Priority 6/10
Explain Dismiss

load used to dynamically load code

../../src/main/java/com/taobao/weex/utils/WXSoInstallMgrSdk.java:469: Dynamically loading code using load is risky, please use loadLibrary instead when possible
 466         if (mSoLoader != null) {
 467           mSoLoader.doLoad(_targetSoFile(libName, version));
 468         } else {
 469           System.load(_targetSoFile(libName, version));                                             
 470         }
 471       }
 472       initSuc = true;
Dynamically loading code from locations other than the application's library directory or the Android platform's built-in library directories is dangerous, as there is an increased risk that the code could have been tampered with. Applications should use loadLibrary when possible, which provides increased assurance that libraries are loaded from one of these safer locations. Application developers should use the features of their development environment to place application native libraries into the lib directory of their compiled APKs.
To suppress this error, use the issue id "UnsafeDynamicallyLoadedCode" as explained in the Suppressing Warnings and Errors section.

UnsafeDynamicallyLoadedCode Security Warning Priority 4/10
Explain Dismiss

Memory allocations within drawing code

../../src/main/java/com/taobao/weex/ui/view/refresh/circlebar/CircleProgressBar.java:144: Avoid object allocations during draw/layout operations (preallocate and reuse instead)
 141       mShadowRadius = (int) (density * SHADOW_RADIUS);
 142 
 143       if (elevationSupported()) {
 144         mBgCircle = new ShapeDrawable(new OvalShape());                                             
 145         ViewCompat.setElevation(this, SHADOW_ELEVATION * density);
 146       } else {
 147         OvalShape oval = new OvalShadow(mShadowRadius, mDiameter - mShadowRadius * 2);

../../src/main/java/com/taobao/weex/ui/view/refresh/circlebar/CircleProgressBar.java:144: Avoid object allocations during draw/layout operations (preallocate and reuse instead)


141 mShadowRadius = (int) (density * SHADOW_RADIUS);
142
143 if (elevationSupported()) {
144 mBgCircle = new ShapeDrawable(new OvalShape());                                             
145 ViewCompat.setElevation(this, SHADOW_ELEVATION * density);
146 } else {
147 OvalShape oval = new OvalShadow(mShadowRadius, mDiameter - mShadowRadius * 2);

../../src/main/java/com/taobao/weex/ui/view/refresh/circlebar/CircleProgressBar.java:147: Avoid object allocations during draw/layout operations (preallocate and reuse instead)


144 mBgCircle = new ShapeDrawable(new OvalShape());
145 ViewCompat.setElevation(this, SHADOW_ELEVATION * density);
146 } else {
147 OvalShape oval = new OvalShadow(mShadowRadius, mDiameter - mShadowRadius * 2);              
148 mBgCircle = new ShapeDrawable(oval);
149 ViewCompat.setLayerType(this, ViewCompat.LAYER_TYPE_SOFTWARE, mBgCircle.getPaint());
150 mBgCircle.getPaint().setShadowLayer(mShadowRadius, shadowXOffset, shadowYOffset,

../../src/main/java/com/taobao/weex/ui/view/refresh/circlebar/CircleProgressBar.java:148: Avoid object allocations during draw/layout operations (preallocate and reuse instead)


145 ViewCompat.setElevation(this, SHADOW_ELEVATION * density);
146 } else {
147 OvalShape oval = new OvalShadow(mShadowRadius, mDiameter - mShadowRadius * 2);
148 mBgCircle = new ShapeDrawable(oval);                                                        
149 ViewCompat.setLayerType(this, ViewCompat.LAYER_TYPE_SOFTWARE, mBgCircle.getPaint());
150 mBgCircle.getPaint().setShadowLayer(mShadowRadius, shadowXOffset, shadowYOffset,
151 KEY_SHADOW_COLOR);

You should avoid allocating objects during a drawing or layout operation. These are called frequently, so a smooth UI can be interrupted by garbage collection pauses caused by the object allocations.

The way this is generally handled is to allocate the needed objects up front and to reuse them for each drawing operation.

Some methods allocate memory on your behalf (such as Bitmap.create), and these should be handled in the same way.
To suppress this error, use the issue id "DrawAllocation" as explained in the Suppressing Warnings and Errors section.

DrawAllocation Performance Warning Priority 9/10
Explain Dismiss

Obsolete SDK_INT Version Check

../../src/main/java/com/taobao/weex/ui/view/refresh/core/WXSwipeLayout.java:699: Unnecessary; SDK_INT is never < 14
 696     if (mTargetView == null) {
 697       return false;
 698     }
 699     if (Build.VERSION.SDK_INT < 14) {                                                               
 700       if (mTargetView instanceof AbsListView) {
 701         final AbsListView absListView = (AbsListView) mTargetView;
 702         return absListView.getChildCount() > 0

../../src/main/java/com/taobao/weex/ui/view/refresh/core/WXSwipeLayout.java:721: Unnecessary; SDK_INT is never < 14


718 if (mTargetView == null) {
719 return false;
720 }
721 if (Build.VERSION.SDK_INT < 14) {                                                               
722 if (mTargetView instanceof AbsListView) {
723 final AbsListView absListView = (AbsListView) mTargetView;
724 if (absListView.getChildCount() > 0) {

This check flags version checks that are not necessary, because the minSdkVersion (or surrounding known API level) is already at least as high as the version checked for.

Similarly, it also looks for resources in -vNN folders, such as values-v14 where the version qualifier is less than or equal to the minSdkVersion, where the contents should be merged into the best folder.
Note: This issue has an associated quickfix operation in Android Studio and IntelliJ IDEA.
To suppress this error, use the issue id "ObsoleteSdkInt" as explained in the Suppressing Warnings and Errors section.

ObsoleteSdkInt Performance Warning Priority 6/10
Explain Dismiss

Static Field Leaks

../../src/main/java/com/taobao/weex/utils/WXSoInstallMgrSdk.java:79: Do not place Android context classes in static fields; this is a memory leak (and also breaks Instant Run)
  76   private final static String STARTUPSO = "/libweexjsb.so";
  77   private final static String STARTUPSOANDROID15 = "/libweexjst.so";
  78 
  79   static Context mContext = null;                                                                   
  80   private static IWXSoLoaderAdapter mSoLoader = null;
  81   private static IWXStatisticsListener mStatisticsListener = null;
A static field will leak contexts.

Non-static inner classes have an implicit reference to their outer class. If that outer class is for example a Fragment or Activity, then this reference means that the long-running handler/loader/task will hold a reference to the activity which prevents it from getting garbage collected.

Similarly, direct field references to activities and fragments from these longer running instances can cause leaks.

ViewModel classes should never point to Views or non-application Contexts.
To suppress this error, use the issue id "StaticFieldLeak" as explained in the Suppressing Warnings and Errors section.

StaticFieldLeak Performance Warning Priority 6/10
Explain Dismiss

HashMap can be replaced with SparseArray

../../src/main/java/com/taobao/weex/ui/module/WXTimerModule.java:66: Use new SparseIntArray(...) instead for better performance
  63 
  64   public WXTimerModule() {
  65     handler = new Handler(WXBridgeManager.getInstance().getJSLooper(), this);
  66     antiIntAutoBoxing = new SparseArray<>();                                                        
  67   }
  68 
For maps where the keys are of type integer, it's typically more efficient to use the Android SparseArray API. This check identifies scenarios where you might want to consider using SparseArray instead of HashMap for better performance.

This is particularly useful when the value types are primitives like ints, where you can use SparseIntArray and avoid auto-boxing the values from int to Integer.

If you need to construct a HashMap because you need to call an API outside of your control which requires a Map, you can suppress this warning using for example the @SuppressLint annotation.
To suppress this error, use the issue id "UseSparseArrays" as explained in the Suppressing Warnings and Errors section.

UseSparseArrays Performance Warning Priority 4/10
Explain Dismiss

Should use valueOf instead of new

../../src/main/java/com/taobao/weex/bridge/WXJSObject.java:57: Use Double.valueOf(((Integer) object).intValue()) instead
 54         data = object;
 55         if (object instanceof Integer) {
 56             type = NUMBER;
 57             data = new Double(((Integer) object).intValue());                                       
 58         } else if (object instanceof Double) {
 59             type = NUMBER;
 60         } else if (object instanceof Float) {

../../src/main/java/com/taobao/weex/bridge/WXJSObject.java:62: Use Double.valueOf(((Float) object).intValue()) instead


59 type = NUMBER;
60 } else if (object instanceof Float) {
61 type = NUMBER;
62 data = new Double(((Float) object).intValue());                                         
63 } else if (object instanceof String) {
64 type = String;
65 } else if (object instanceof Object) {

../../src/main/java/com/taobao/weex/ui/component/WXScroller.java:511: Use Boolean.valueOf(isLayoutRTL()) instead


508 scrollView.scrollBy(changedWidth, component.getScrollY());
509 }
510 }
511 mIslastDirectionRTL = new Boolean(isLayoutRTL());                                     
512 }
513 });
514 }

You should not call the constructor for wrapper classes directly, such as`new Integer(42)`. Instead, call the valueOf factory method, such as Integer.valueOf(42). This will typically use less memory because common integers such as 0 and 1 will share a single instance.
Note: This issue has an associated quickfix operation in Android Studio and IntelliJ IDEA.
To suppress this error, use the issue id "UseValueOf" as explained in the Suppressing Warnings and Errors section.

UseValueOf Performance Warning Priority 4/10
Explain Dismiss

Image defined in density-independent drawable folder

../../src/main/res/drawable/weex_error.png: Found bitmap drawable res/drawable/weex_error.png in densityless folder
The res/drawable folder is intended for density-independent graphics such as shapes defined in XML. For bitmaps, move it to drawable-mdpi and consider providing higher and lower resolution versions in drawable-ldpi, drawable-hdpi and drawable-xhdpi. If the icon really is density independent (for example a solid color) you can place it in drawable-nodpi.
To suppress this error, use the issue id "IconLocation" as explained in the Suppressing Warnings and Errors section.

IconLocation Icons Usability Warning Priority 5/10
Explain Dismiss

Missing View constructors for XML inflation

../../src/main/java/com/taobao/weex/ui/view/refresh/wrapper/BounceRecyclerView.java:33: Custom view BounceRecyclerView is missing constructor used by tools: (Context) or (Context,AttributeSet) or (Context,AttributeSet,int)
  30 import com.taobao.weex.ui.view.listview.WXRecyclerView;
  31 import com.taobao.weex.ui.view.listview.adapter.RecyclerViewBaseAdapter;
  32 
  33 public class BounceRecyclerView extends BaseBounceView<WXRecyclerView> implements ListComponentView,WXGestureObservable {
  34 
  35   public static final int DEFAULT_COLUMN_COUNT = 1;
  36   public static final int DEFAULT_COLUMN_GAP = 1;

../../src/main/java/com/taobao/weex/ui/view/refresh/wrapper/BounceScrollerView.java:26: Custom view BounceScrollerView is missing constructor used by tools: (Context) or (Context,AttributeSet) or (Context,AttributeSet,int)


23 import com.taobao.weex.ui.component.WXScroller;
24 import com.taobao.weex.ui.view.WXScrollView;
25
26 public class BounceScrollerView extends BaseBounceView<WXScrollView> {                              
27
28 public BounceScrollerView(Context context, int orientation, WXScroller waScroller) {
29 super(context,orientation);

Some layout tools (such as the Android layout editor) need to find a constructor with one of the following signatures:
* View(Context context)
* View(Context context, AttributeSet attrs)
* View(Context context, AttributeSet attrs, int defStyle)

If your custom view needs to perform initialization which does not apply when used in a layout editor, you can surround the given code with a check to see if View#isInEditMode() is false, since that method will return false at runtime but true within a user interface editor.
To suppress this error, use the issue id "ViewConstructor" as explained in the Suppressing Warnings and Errors section.

ViewConstructor Usability Warning Priority 3/10
Explain Dismiss

Accessibility in Custom Views

../../src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java:941: onTouch should call View#performClick when a click is detected
  938           View anchor = anchorComponent.getHostView();
  939           anchor.setOnTouchListener(new View.OnTouchListener() {
  940             @Override
  941             public boolean onTouch(View v, MotionEvent event) {                                     
  942               if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
  943                 mDragHelper.startDrag(holder);
  944               }

../../src/main/java/com/taobao/weex/ui/component/pesudo/TouchActivePseudoListener.java:37: TouchActivePseudoListener#onTouch should call View#performClick when a click is detected


34 }
35
36 @Override
37 public boolean onTouch(View v, MotionEvent event) {                                               
38 int action = event.getAction();
39 if (mOnActivePseudoListner != null) {
40 if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_DOWN) {

../../src/main/java/com/taobao/weex/ui/view/WXCircleViewPager.java:154: Custom view WXCircleViewPager overrides onTouchEvent but not performClick


151 }
152
153 @Override
154 public boolean onTouchEvent(MotionEvent ev) {                                                     
155 if(!scrollable) {
156 return true;
157 }

../../src/main/java/com/taobao/weex/ui/view/WXEditText.java:69: Custom view WXEditText overrides onTouchEvent but not performClick


66 }
67
68 @Override
69 public boolean onTouchEvent(MotionEvent event) {                                                  
70 boolean result = super.onTouchEvent(event);
71 if (wxGesture != null) {
72 result |= wxGesture.onTouch(this, event);

../../src/main/java/com/taobao/weex/ui/view/gesture/WXGesture.java:211: WXGesture#onTouch should call View#performClick when a click is detected


208 }
209
210 @Override
211 public boolean onTouch(View v, MotionEvent event) {                                               
212 if(requestDisallowInterceptTouchEvent){
213 requestDisallowInterceptTouchEvent = false;
214 return false;

+ 13 More Occurrences...

../../src/main/java/com/taobao/weex/ui/view/WXHorizontalScrollView.java:109: Custom view WXHorizontalScrollView overrides onTouchEvent but not performClick
 106   }
 107 
 108   @Override
 109   public boolean onTouchEvent(MotionEvent ev) {                                                     
 110     if(!scrollable) {
 111       return true; // when scrollable is set to false, then eat the touch event
 112     }

../../src/main/java/com/taobao/weex/ui/view/WXImageView.java:110: Custom view WXImageView overrides onTouchEvent but not performClick


107 }
108
109 @Override
110 public boolean onTouchEvent(MotionEvent event) {                                                  
111 boolean result = super.onTouchEvent(event);
112 if (wxGesture != null) {
113 result |= wxGesture.onTouch(this, event);

../../src/main/java/com/taobao/weex/ui/view/listview/WXRecyclerView.java:92: Custom view WXRecyclerView overrides onTouchEvent but not performClick


89 }
90
91 @Override
92 public boolean onTouchEvent(MotionEvent event) {                                                  
93 if(!scrollable) {
94 return true;
95 }

../../src/main/java/com/taobao/weex/ui/component/richtext/WXRichTextView.java:41: Custom view WXRichTextView overrides onTouchEvent but not performClick


38 }
39
40 @Override
41 public boolean onTouchEvent(MotionEvent event) {                                                  
42 boolean superResult = super.onTouchEvent(event);
43 boolean handled = false;
44 if (isEnabled() && getTextLayout() != null && getText() instanceof Spannable) {

../../src/main/java/com/taobao/weex/ui/view/WXScrollView.java:186: Custom view WXScrollView overrides onTouchEvent but not performClick


183 }
184
185 @Override
186 public boolean onTouchEvent(MotionEvent ev) {                                                     
187 if(!scrollable) {
188 return true; // when scrollable is set to false, then eat the touch event
189 }

../../src/main/java/com/taobao/weex/ui/component/WXScroller.java:531: Custom view <code>WXHorizontalScrollView</code> has setOnTouchListener called on it but does not override performClick


528
529 if(pageEnable) {
530 mGestureDetector = new GestureDetector(new MyGestureDetector(scrollView));
531 scrollView.setOnTouchListener(new View.OnTouchListener() {                                  
532 @Override
533 public boolean onTouch(View v, MotionEvent event) {
534 if (pageSize == 0) {

../../src/main/java/com/taobao/weex/ui/component/WXScroller.java:533: onTouch should call View#performClick when a click is detected


530 mGestureDetector = new GestureDetector(new MyGestureDetector(scrollView));
531 scrollView.setOnTouchListener(new View.OnTouchListener() {
532 @Override
533 public boolean onTouch(View v, MotionEvent event) {                                       
534 if (pageSize == 0) {
535 pageSize = v.getMeasuredWidth();
536 }

../../src/main/java/com/taobao/weex/ui/component/WXSlider.java:564: Custom view <code>WXCircleViewPager</code> has setOnTouchListener called on it but does not override performClick


561 if (isInfinite) {
562 if (mAdapter.getRealCount() == 2) {
563 final GestureDetector gestureDetector = new GestureDetector(getContext(), new FlingGestureListener(mViewPager));
564 mViewPager.setOnTouchListener(new View.OnTouchListener() {                                  
565 @Override
566 public boolean onTouch(View v, MotionEvent event) {
567 return gestureDetector.onTouchEvent(event);

../../src/main/java/com/taobao/weex/ui/component/WXSlider.java:566: onTouch should call View#performClick when a click is detected


563 final GestureDetector gestureDetector = new GestureDetector(getContext(), new FlingGestureListener(mViewPager));
564 mViewPager.setOnTouchListener(new View.OnTouchListener() {
565 @Override
566 public boolean onTouch(View v, MotionEvent event) {                                       
567 return gestureDetector.onTouchEvent(event);
568 }
569 });

../../src/main/java/com/taobao/weex/ui/component/WXSlider.java:571: Custom view <code>WXCircleViewPager</code> has setOnTouchListener called on it but does not override performClick


568 }
569 });
570 } else {
571 mViewPager.setOnTouchListener(null);                                                        
572 }
573 }
574 }

../../src/main/java/com/taobao/weex/ui/view/WXSwitchView.java:50: Custom view WXSwitchView overrides onTouchEvent but not performClick


47 }
48
49 @Override
50 public boolean onTouchEvent(MotionEvent event) {                                                  
51 boolean result = super.onTouchEvent(event);
52 if (wxGesture != null) {
53 result |= wxGesture.onTouch(this, event);

../../src/main/java/com/taobao/weex/ui/view/WXTextView.java:69: Custom view WXTextView overrides onTouchEvent but not performClick


66 }
67
68 @Override
69 public boolean onTouchEvent(MotionEvent event) {                                                  
70 boolean result = super.onTouchEvent(event);
71 if (wxGesture != null) {
72 result |= wxGesture.onTouch(this, event);

../../src/main/java/com/taobao/weex/ui/view/WXVideoView.java:68: Custom view WXVideoView overrides onTouchEvent but not performClick


65 }
66
67 @Override
68 public boolean onTouchEvent(MotionEvent event) {                                                  
69 boolean result = super.onTouchEvent(event);
70 if (wxGesture != null) {
71 result |= wxGesture.onTouch(this, event);

If a View that overrides onTouchEvent or uses an OnTouchListener does not also implement performClick and call it when clicks are detected, the View may not handle accessibility actions properly. Logic handling the click actions should ideally be placed in View#performClick as some accessibility services invoke performClick when a click action should occur.
To suppress this error, use the issue id "ClickableViewAccessibility" as explained in the Suppressing Warnings and Errors section.

ClickableViewAccessibility Accessibility Warning Priority 6/10
Explain Dismiss

Using left/right instead of start/end attributes

../../src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java:187: Use "Gravity.END" instead of "Gravity.RIGHT" to ensure correct behavior in right-to-left locales
  184       if (lp instanceof FrameLayout.LayoutParams) {
  185         FrameLayout.LayoutParams lp_frameLayout = (FrameLayout.LayoutParams) lp;
  186         if (this.isLayoutRTL()) {
  187           lp_frameLayout.gravity = Gravity.RIGHT | Gravity.TOP;                                     
  188           lp.setMargins(right, top, left, bottom);
  189         } else {
  190           lp_frameLayout.gravity = Gravity.LEFT | Gravity.TOP;

../../src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java:190: Use "Gravity.START" instead of "Gravity.LEFT" to ensure correct behavior in right-to-left locales


187 lp_frameLayout.gravity = Gravity.RIGHT | Gravity.TOP;
188 lp.setMargins(right, top, left, bottom);
189 } else {
190 lp_frameLayout.gravity = Gravity.LEFT | Gravity.TOP;                                      
191 lp.setMargins(left, top, right, bottom);
192 }
193 } else {

../../src/main/java/com/taobao/weex/ui/component/WXComponent.java:254: Use "Gravity.START" instead of "Gravity.LEFT" to ensure correct behavior in right-to-left locales


251 lp.setMargins(left, top, right, bottom);
252 if (lp instanceof FrameLayout.LayoutParams) {
253 FrameLayout.LayoutParams lp_frameLayout = (FrameLayout.LayoutParams) lp;
254 lp_frameLayout.gravity = Gravity.LEFT | Gravity.TOP;                                      
255 }
256 }

../../src/main/java/com/taobao/weex/ui/component/WXScroller.java:402: Use "Gravity.END" instead of "Gravity.RIGHT" to ensure correct behavior in right-to-left locales


399 if (lp instanceof FrameLayout.LayoutParams) {
400 FrameLayout.LayoutParams lp_frameLayout = (FrameLayout.LayoutParams) lp;
401 if (isLayoutRTL()) {
402 lp_frameLayout.gravity = Gravity.RIGHT | Gravity.TOP;                                     
403 lp.setMargins(right, top, left, bottom);
404 } else {
405 lp_frameLayout.gravity = Gravity.LEFT | Gravity.TOP;

../../src/main/java/com/taobao/weex/ui/component/WXScroller.java:405: Use "Gravity.START" instead of "Gravity.LEFT" to ensure correct behavior in right-to-left locales


402 lp_frameLayout.gravity = Gravity.RIGHT | Gravity.TOP;
403 lp.setMargins(right, top, left, bottom);
404 } else {
405 lp_frameLayout.gravity = Gravity.LEFT | Gravity.TOP;                                      
406 lp.setMargins(left, top, right, bottom);
407 }
408 } else {

Using Gravity#LEFT and Gravity#RIGHT can lead to problems when a layout is rendered in locales where text flows from right to left. Use Gravity#START and Gravity#END instead. Similarly, in XML gravity and layout_gravity attributes, use start rather than left.

For XML attributes such as paddingLeft and layout_marginLeft, use paddingStart and layout_marginStart. NOTE: If your minSdkVersion is less than 17, you should add both the older left/right attributes as well as the new start/right attributes. On older platforms, where RTL is not supported and the start/right attributes are unknown and therefore ignored, you need the older left/right attributes. There is a separate lint check which catches that type of error.

(Note: For Gravity#LEFT and Gravity#START, you can use these constants even when targeting older platforms, because the start bitmask is a superset of the left bitmask. Therefore, you can use gravity="start" rather than gravity="left|start".)
Note: This issue has an associated quickfix operation in Android Studio and IntelliJ IDEA.
To suppress this error, use the issue id "RtlHardcoded" as explained in the Suppressing Warnings and Errors section.

RtlHardcoded Bidirectional Text Internationalization Warning Priority 5/10
Explain Dismiss

Generated by 🚫 dangerJS against fddd73a

.travis.yml Outdated Show resolved Hide resolved
dangerfile-static-check.js Outdated Show resolved Hide resolved
dangerfile-output.js Outdated Show resolved Hide resolved
Dangerfile Outdated
@@ -0,0 +1 @@
code_style_validation.check file_extensions: ['.cc', '.cpp', '.m', 'mm', '.h', '.java']
Copy link
Contributor

@YorkShen YorkShen Aug 2, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct me if I am wrong.

It seems like you are using the ruby version of danger for code_format, and the ruby version danger will some use Dangerfile as its source.

If this is the case, relying on https://github.com/wrmswindmill/danger-code_style_validation.git is not an option in my knowledge, as the source file could be changed in any minutes. At least, you should rely a publish version of https://github.com/wrmswindmill/danger-code_style_validation.git. I suggest you share your ideas in the mailing list.

PS:

  1. I don't see the output of the code format in danger.
  2. You should also provide a format script or file, within which developers could import the file into their IDE( XCode or Android Studio) and format code with one click.

.travis.yml Outdated Show resolved Hide resolved
@YorkShen YorkShen added this to the Weex 0.27 milestone Aug 6, 2019
Copy link
Contributor

@YorkShen YorkShen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, there is a conflict.

.travis.yml Outdated Show resolved Hide resolved
Copy link
Contributor

@YorkShen YorkShen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution.

I know debugging Travis-CI is a time-consuming and tedious task and I'm really appreciated your help in improving Weex CI

@YorkShen YorkShen merged commit 3bfb619 into apache:master Aug 8, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants