www.gusucode.com > appdesigner工具箱matlab源码程序 > appdesigner/+appdesigner/+internal/+appalert/AppException.m
classdef AppException < MException %APPEXCEPTION Captures App Designer app error information % An AppException decorates the actual MException thrown by the app. % It truncates stack frames that are unnecessary and don't provide % any value to the user % Copyright 2014 - 2015 The MathWorks, Inc. properties ErrorLineInApp end properties (Access = private) Exception AppFullFileName TruncatedStack end methods function obj = AppException(mException, appFullFileName) if(strcmpi(mException.identifier, 'MATLAB:ui:uiaxes:general') ||... strcmpi(mException.identifier, 'MATLAB:ui:uiaxes:threedim')) % UIAxes - specific % Replace the anchor tag with a different anchor tag % because the original anchor tag % is of the form % <a href="matlab:helpview('//mathworks/devel/sbs/29/tmccabe.appd_doc/matlab/help/matlab/creating_guis/app-designer-graphics-support.html')"> % but this does not work in CEF % Custom event handlers are wired on the client to look for % the CSS class thats specified here message = regexprep(mException.message, '<a.*?>', '<a href = "#" class = "ad-graphics-support-runtime-link">'); else % Remove any html tags from the MException message % This is primarily for syntax errors that break the class % code (it fails upon code parsing prior to executing) message = regexprep(mException.message, '<[^>]*>', ''); end % Call MException constructor to setup the identifier and % message properties obj@MException(mException.identifier, '%s', message); % Update the type to be the same as the input MException. This % needs to be done so that getReport() works properly. obj.type = mException.type; % Update the cause field to be the same as the input MException % This needs to be done so that getReport() works properly. for i=1:length(mException.cause) obj = addCause(obj,mException.cause{i}); end obj.Exception = mException; obj.AppFullFileName = appFullFileName; % Truncate the MException's stack to remove the unnecessary % stack frames obj.TruncatedStack = obj.truncateStack(obj.Exception.stack); obj.ErrorLineInApp = obj.getErrorLineInApp(); end end methods (Access = protected) function stack = getStack(obj) % STACK = GETSTACK(OBJ) This method overrides the inherited % GETSTACK method from MException. It returns the truncated % stack. It is necessary to override this method so that the % method GETREPORT generates a the correct message based on the % truncated stack. stack = obj.TruncatedStack; end function stack = truncateStack(obj, stack) % STACK = TRUNCATESTCK(OBJ, STACK) This method truncate an % MException stack by removing frames that show the inner % workings of the callback handling which adds no value. % Find the first and last stack frames that pertain to the % running app. fileNames = {stack.file}; hits = strcmp(obj.AppFullFileName, fileNames); firstIndex = find(hits,1,'first'); lastIndex = find(hits,1,'last'); % The stack does not have the running app in one of its frame. % Therefore, it is a parsing error and all the frames should be % removed. if isempty(lastIndex) lastIndex = 0; end % Create an array of stack frames to be removed % Remove the first frame pertaining to the app as well as all % the frames after the last frame belonging to the app. toBeRemvoedIndex = [firstIndex, lastIndex+1:numel(stack)]; % Handle startup exception - only keep the frame referencing the % contstructor that call the startup function [~, appName] = fileparts(obj.AppFullFileName); if ~isempty(firstIndex) && strcmp(stack(firstIndex).name, [appName '.startup']) toBeRemvoedIndex = [toBeRemvoedIndex, firstIndex+1:lastIndex]; end stack(toBeRemvoedIndex) = []; end function line = getErrorLineInApp(obj) % LINE = GETERRORLINEINAPP(OBJ) This method gets the line % number where the exception occurs/surfaces in the running % app's code. line = 1; stack = obj.Exception.stack; % Finds the first non-truncated stack frame with the same file % path as this app for i=1:length(stack) fileName = stack(i).file; if strcmp(fileName, obj.AppFullFileName) line = stack(i).line; break end end % The error could be due to a failure in parsing the app's % code. In this case there is no stack information that % indicates where the parsing failure is in the app code. % However, the error message itself contains this info and so % it can be extracted out of the message. if line == 1 % Parse out the line number by using a regular express and % tokening off the 'opentoline' hyperlink in the message. % For example: % % Error: <a href="matlab: % opentoline('C:\AppErrorExamples.mlapp',43,42)">File: % AppErrorExamples.mlapp Line: 43 Column: 42 </a>... % [lineAndColumn,~] = regexp(obj.Exception.message,... 'opentoline\(.*\,(\d*),(\d*)\)','tokens','match'); if ~isempty(lineAndColumn) line = str2double(lineAndColumn{1}{1}); end end end end end