1731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar/* 2731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar * Copyright (C) 2015 The Android Open Source Project 3731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar * 4731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License"); 5731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar * you may not use this file except in compliance with the License. 6731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar * You may obtain a copy of the License at 7731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar * 8731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar * http://www.apache.org/licenses/LICENSE-2.0 9731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar * 10731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar * Unless required by applicable law or agreed to in writing, software 11731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS, 12731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar * See the License for the specific language governing permissions and 14731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar * limitations under the License. 15731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar */ 16731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar 17731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarpackage android.databinding.tool.processing; 18731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar 194ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Gupta 204ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Guptaimport com.google.common.base.Joiner; 214ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Guptaimport com.google.common.base.Splitter; 224ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Guptaimport com.google.common.base.Strings; 23731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar 24731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport android.databinding.tool.store.Location; 25731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport android.databinding.tool.util.L; 264ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Guptaimport android.databinding.tool.util.StringUtils; 27731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar 28731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport java.util.ArrayList; 29731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport java.util.List; 30731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport java.util.regex.Matcher; 31731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport java.util.regex.Pattern; 32731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar 33731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar/** 34731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar * An exception that contains scope information. 35731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar */ 36731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarpublic class ScopedException extends RuntimeException { 37731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar public static final String ERROR_LOG_PREFIX = "****/ data binding error ****"; 38731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar public static final String ERROR_LOG_SUFFIX = "****\\ data binding error ****"; 39731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar public static final String MSG_KEY = "msg:"; 40731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar public static final String LOCATION_KEY = "loc:"; 41731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar public static final String FILE_KEY = "file:"; 4208119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar private static boolean sEncodeOutput = false; 43731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar private ScopedErrorReport mScopedErrorReport; 44731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar private String mScopeLog; 45731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar 46731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar public ScopedException(String message, Object... args) { 47fd8342a51a96282df315cd27055ba539e89a8c9eYigit Boyar super(message == null ? "unknown data binding exception" : 48fd8342a51a96282df315cd27055ba539e89a8c9eYigit Boyar args.length == 0 ? message : String.format(message, args)); 49731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar mScopedErrorReport = Scope.createReport(); 50731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar mScopeLog = L.isDebugEnabled() ? Scope.produceScopeLog() : null; 51731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } 52731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar 53731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar ScopedException(String message, ScopedErrorReport scopedErrorReport) { 54731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar super(message); 55731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar mScopedErrorReport = scopedErrorReport; 56731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } 57731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar 58731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar public String getBareMessage() { 59731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar return super.getMessage(); 60731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } 61731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar 62731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar @Override 63731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar public String getMessage() { 6408119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar return sEncodeOutput ? createEncodedMessage() : createHumanReadableMessage(); 6508119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar } 6608119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar 676047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public String createHumanReadableMessage() { 6808119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar ScopedErrorReport scopedError = getScopedErrorReport(); 6908119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar StringBuilder sb = new StringBuilder(); 7008119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar sb.append(super.getMessage()).append("\n") 7108119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar .append("file://").append(scopedError.getFilePath()); 7208119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar if (scopedError.getLocations() != null && scopedError.getLocations().size() > 0) { 7308119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar sb.append(" Line:"); 7408119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar sb.append(scopedError.getLocations().get(0).startLine); 7508119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar } 7608119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar sb.append("\n"); 7708119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar return sb.toString(); 7808119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar } 7908119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar 8008119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar private String createEncodedMessage() { 81731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar ScopedErrorReport scopedError = getScopedErrorReport(); 82731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar StringBuilder sb = new StringBuilder(); 83731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar sb.append(ERROR_LOG_PREFIX) 84731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar .append(MSG_KEY).append(super.getMessage()).append("\n") 85731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar .append(FILE_KEY).append(scopedError.getFilePath()).append("\n"); 86731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar if (scopedError.getLocations() != null) { 87731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar for (Location location : scopedError.getLocations()) { 88731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar sb.append(LOCATION_KEY).append(location.toUserReadableString()).append("\n"); 89731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } 90731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } 91731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar sb.append(ERROR_LOG_SUFFIX); 924ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Gupta return Joiner.on(' ').join(Splitter.on(StringUtils.LINE_SEPARATOR).split(sb)); 93731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } 94731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar 95731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar public ScopedErrorReport getScopedErrorReport() { 96731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar return mScopedErrorReport; 97731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } 98731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar 99731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar public boolean isValid() { 100731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar return mScopedErrorReport.isValid(); 101731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } 102731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar 103731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar public static ScopedException createFromOutput(String output) { 104731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar String message = ""; 105731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar String file = ""; 1069784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar List<Location> locations = new ArrayList<Location>(); 107731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar int msgStart = output.indexOf(MSG_KEY); 108731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar if (msgStart < 0) { 109731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar message = output; 110731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } else { 111731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar int fileStart = output.indexOf(FILE_KEY, msgStart + MSG_KEY.length()); 112731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar if (fileStart < 0) { 113731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar message = output; 114731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } else { 115731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar message = output.substring(msgStart + MSG_KEY.length(), fileStart); 116731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar int locStart = output.indexOf(LOCATION_KEY, fileStart + FILE_KEY.length()); 117731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar if (locStart < 0) { 118731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar file = output.substring(fileStart + FILE_KEY.length()); 119731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } else { 120731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar file = output.substring(fileStart + FILE_KEY.length(), locStart); 121731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar int nextLoc = 0; 122731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar while(nextLoc >= 0) { 123731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar nextLoc = output.indexOf(LOCATION_KEY, locStart + LOCATION_KEY.length()); 124731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar Location loc; 125731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar if (nextLoc < 0) { 126731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar loc = Location.fromUserReadableString( 127731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar output.substring(locStart + LOCATION_KEY.length())); 128731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } else { 129731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar loc = Location.fromUserReadableString( 130731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar output.substring(locStart + LOCATION_KEY.length(), nextLoc)); 131731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } 132731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar if (loc != null && loc.isValid()) { 133731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar locations.add(loc); 134731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } 135731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar locStart = nextLoc; 136731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } 137731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } 138731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } 139731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } 140731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar return new ScopedException(message.trim(), 1414ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Gupta new ScopedErrorReport(Strings.isNullOrEmpty(file) ? null : file.trim(), locations)); 142731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } 143731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar 144731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar public static List<ScopedException> extractErrors(String output) { 1459784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar List<ScopedException> errors = new ArrayList<ScopedException>(); 146731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar int index = output.indexOf(ERROR_LOG_PREFIX); 147731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar final int limit = output.length(); 148731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar while (index >= 0 && index < limit) { 149731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar int end = output.indexOf(ERROR_LOG_SUFFIX, index + ERROR_LOG_PREFIX.length()); 150731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar if (end == -1) { 151731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar errors.add(createFromOutput(output.substring(index + ERROR_LOG_PREFIX.length()))); 152731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar break; 153731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } else { 154731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar errors.add(createFromOutput(output.substring(index + ERROR_LOG_PREFIX.length(), 155731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar end))); 156731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar index = output.indexOf(ERROR_LOG_PREFIX, end + ERROR_LOG_SUFFIX.length()); 157731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } 158731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } 159731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar return errors; 160731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } 16108119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar 16208119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar public static void encodeOutput(boolean encodeOutput) { 16308119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar sEncodeOutput = encodeOutput; 16408119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar } 1659784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 1669784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public static boolean issEncodeOutput() { 1679784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return sEncodeOutput; 1689784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 169731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar} 170