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