pub fn diagnostic_load(&self, sources: Vec<Source>) -> Vec<Diagnostic> {
        // Separate function so that errors returned with `?` are captured.
        fn load_source(source: Source, kb: &mut KnowledgeBase) -> PolarResult<Vec<Diagnostic>> {
            if let Some(ref filename) = source.filename {
                kb.add_source(filename, &source.src)?;
            }
            // TODO(gj): we still bomb out at the first ParseError.
            let mut lines = parser::parse_lines(source)?;
            lines.reverse();
            let mut diagnostics = vec![];
            while let Some(line) = lines.pop() {
                match line {
                    parser::Line::Rule(rule) => {
                        diagnostics.append(&mut check_singletons(&rule, kb));
                        diagnostics.append(&mut check_ambiguous_precedence(&rule));
                        let rule = rewrite_rule(rule, kb);
                        kb.add_rule(rule);
                    }
                    parser::Line::Query(term) => {
                        kb.inline_queries.push(term);
                    }
                    parser::Line::RuleType(rule_type) => {
                        // make sure rule_type doesn't have anything that needs to be rewritten in the head
                        let rule_type = rewrite_rule(rule_type, kb);
                        if !matches!(
                            rule_type.body.value(),
                            Value::Expression(
                                Operation {
                                    operator: Operator::And,
                                    args
                                }
                            ) if args.is_empty()
                        ) {
                            diagnostics.push(Diagnostic::Error(
                                ValidationError::InvalidRuleType {
                                    rule_type,
                                    msg: "Rule types cannot contain dot lookups.".into(),
                                }
                                .into(),
                            ));
                        } else {
                            kb.add_rule_type(rule_type);
                        }
                    }
                    parser::Line::ResourceBlock {
                        keyword,
                        resource,
                        productions,
                    } => {
                        let (block, mut errors) =
                            resource_block_from_productions(keyword, resource, productions);
                        errors.append(&mut block.add_to_kb(kb));
                        diagnostics.extend(errors.into_iter().map(Into::into));
                    }
                }
            }
            Ok(diagnostics)
        }

        let mut kb = self.kb.write().unwrap();
        let mut diagnostics = vec![];

        for source in sources {
            match load_source(source, &mut kb) {
                Ok(mut ds) => diagnostics.append(&mut ds),
                Err(e) => diagnostics.push(Diagnostic::Error(e)),
            }
        }

        // NOTE(gj): need to bomb out before rewriting shorthand rules to avoid emitting
        // correct-but-unhelpful errors, e.g., when there's an invalid `relations` declaration that
        // will result in a second error when rewriting a shorthand rule involving the relation
        // that would only distract from the _actual_ error (the invalid `relations` declaration).
        if diagnostics.iter().any(Diagnostic::is_unrecoverable) {
            return diagnostics;
        }

        // Rewrite shorthand rules in resource blocks before validating rule types.
        diagnostics.extend(kb.rewrite_shorthand_rules().into_iter().map(Into::into));

        // NOTE(gj): need to bomb out before rule type validation in case additional rule types
        // were defined later on in the file that encountered the unrecoverable error. Those
        // additional rule types might extend the valid shapes for a rule type defined in a
        // different, well-parsed file that also contains rules that don't conform to the shapes
        // laid out in the well-parsed file but *would have* conformed to the shapes laid out in
        // the file that failed to parse.
        if diagnostics.iter().any(Diagnostic::is_unrecoverable) {
            return diagnostics;
        }

        // Generate appropriate rule_type definitions using the types contained in policy resource
        // blocks.
        if let Err(e) = kb.create_resource_specific_rule_types() {
            diagnostics.push(e.into());
        }

        // check rules are valid against rule types
        diagnostics.append(&mut kb.validate_rules());

        // Perform validation checks against the whole policy
        if !self.ignore_no_allow_warning {
            if let Some(w) = check_no_allow_rule(&kb) {
                diagnostics.push(w)
            }
        }

        // Check for has_permission calls alongside resource block definitions
        if let Some(w) = check_resource_blocks_missing_has_permission(&kb) {
            diagnostics.push(Diagnostic::Warning(w.into()))
        };

        diagnostics
    }
/// Load `sources` into the KB, returning compile-time diagnostics accumulated during the load.
Load `sources` into the KB, returning compile-time diagnostics accumulated during the load.
Load ` sources ` into the KB returning compile - time diagnostics accumulated during the load .
pub fn diagnostic_load(&self, sources: Vec<Source>) -> Vec<Diagnostic> {
        // Separate function so that errors returned with `?` are captured.
        fn load_source(source: Source, kb: &mut KnowledgeBase) -> PolarResult<Vec<Diagnostic>> {
            if let Some(ref filename) = source.filename {
                kb.add_source(filename, &source.src)?;
            }
            // TODO(gj): we still bomb out at the first ParseError.
            let mut lines = parser::parse_lines(source)?;
            lines.reverse();
            let mut diagnostics = vec![];
            while let Some(line) = lines.pop() {
                match line {
                    parser::Line::Rule(rule) => {
                        diagnostics.append(&mut check_singletons(&rule, kb));
                        diagnostics.append(&mut check_ambiguous_precedence(&rule));
                        let rule = rewrite_rule(rule, kb);
                        kb.add_rule(rule);
                    }
                    parser::Line::Query(term) => {
                        kb.inline_queries.push(term);
                    }
                    parser::Line::RuleType(rule_type) => {
                        // make sure rule_type doesn't have anything that needs to be rewritten in the head
                        let rule_type = rewrite_rule(rule_type, kb);
                        if !matches!(
                            rule_type.body.value(),
                            Value::Expression(
                                Operation {
                                    operator: Operator::And,
                                    args
                                }
                            ) if args.is_empty()
                        ) {
                            diagnostics.push(Diagnostic::Error(
                                ValidationError::InvalidRuleType {
                                    rule_type,
                                    msg: "Rule types cannot contain dot lookups.".into(),
                                }
                                .into(),
                            ));
                        } else {
                            kb.add_rule_type(rule_type);
                        }
                    }
                    parser::Line::ResourceBlock {
                        keyword,
                        resource,
                        productions,
                    } => {
                        let (block, mut errors) =
                            resource_block_from_productions(keyword, resource, productions);
                        errors.append(&mut block.add_to_kb(kb));
                        diagnostics.extend(errors.into_iter().map(Into::into));
                    }
                }
            }
            Ok(diagnostics)
        }
        let mut kb = self.kb.write().unwrap();
        let mut diagnostics = vec![];
        for source in sources {
            match load_source(source, &mut kb) {
                Ok(mut ds) => diagnostics.append(&mut ds),
                Err(e) => diagnostics.push(Diagnostic::Error(e)),
            }
        }
        // NOTE(gj): need to bomb out before rewriting shorthand rules to avoid emitting
        // correct-but-unhelpful errors, e.g., when there's an invalid `relations` declaration that
        // will result in a second error when rewriting a shorthand rule involving the relation
        // that would only distract from the _actual_ error (the invalid `relations` declaration).
        if diagnostics.iter().any(Diagnostic::is_unrecoverable) {
            return diagnostics;
        }
        // Rewrite shorthand rules in resource blocks before validating rule types.
        diagnostics.extend(kb.rewrite_shorthand_rules().into_iter().map(Into::into));
        // NOTE(gj): need to bomb out before rule type validation in case additional rule types
        // were defined later on in the file that encountered the unrecoverable error. Those
        // additional rule types might extend the valid shapes for a rule type defined in a
        // different, well-parsed file that also contains rules that don't conform to the shapes
        // laid out in the well-parsed file but *would have* conformed to the shapes laid out in
        // the file that failed to parse.
        if diagnostics.iter().any(Diagnostic::is_unrecoverable) {
            return diagnostics;
        }
        // Generate appropriate rule_type definitions using the types contained in policy resource
        // blocks.
        if let Err(e) = kb.create_resource_specific_rule_types() {
            diagnostics.push(e.into());
        }
        // check rules are valid against rule types
        diagnostics.append(&mut kb.validate_rules());
        // Perform validation checks against the whole policy
        if !self.ignore_no_allow_warning {
            if let Some(w) = check_no_allow_rule(&kb) {
                diagnostics.push(w)
            }
        }
        // Check for has_permission calls alongside resource block definitions
        if let Some(w) = check_resource_blocks_missing_has_permission(&kb) {
            diagnostics.push(Diagnostic::Warning(w.into()))
        };
        diagnostics
    }
pub fn diagnostic_load ( & self , sources : Vec < Source > ) -> Vec < Diagnostic > { // Separate function so that errors returned with `?` are captured. fn load_source ( source : Source , kb : & mut KnowledgeBase ) -> PolarResult < Vec < Diagnostic > > { if let Some ( ref filename ) = source . filename { kb . add_source ( filename , & source . src ) ? ; } // TODO(gj): we still bomb out at the first ParseError. let mut lines = parser :: parse_lines ( source ) ? ; lines . reverse ( ) ; let mut diagnostics = vec ! [ ] ; while let Some ( line ) = lines . pop ( ) { match line { parser :: Line :: Rule ( rule ) => { diagnostics . append ( & mut check_singletons ( & rule , kb ) ) ; diagnostics . append ( & mut check_ambiguous_precedence ( & rule ) ) ; let rule = rewrite_rule ( rule , kb ) ; kb . add_rule ( rule ) ; } parser :: Line :: Query ( term ) => { kb . inline_queries . push ( term ) ; } parser :: Line :: RuleType ( rule_type ) => { // make sure rule_type doesn't have anything that needs to be rewritten in the head let rule_type = rewrite_rule ( rule_type , kb ) ; if ! matches ! ( rule_type body value ( ) Value Expression ( Operation { operator Operator And args } ) if args is_empty ( ) ) { diagnostics . push ( Diagnostic :: Error ( ValidationError :: InvalidRuleType { rule_type , msg : " " . into ( ) , } . into ( ) , ) ) ; } else { kb . add_rule_type ( rule_type ) ; } } parser :: Line :: ResourceBlock { keyword , resource , productions , } => { let ( block , mut errors ) = resource_block_from_productions ( keyword , resource , productions ) ; errors . append ( & mut block . add_to_kb ( kb ) ) ; diagnostics . extend ( errors . into_iter ( ) . map ( Into :: into ) ) ; } } } Ok ( diagnostics ) } let mut kb = self . kb . write ( ) . unwrap ( ) ; let mut diagnostics = vec ! [ ] ; for source in sources { match load_source ( source , & mut kb ) { Ok ( mut ds ) => diagnostics . append ( & mut ds ) , Err ( e ) => diagnostics . push ( Diagnostic :: Error ( e ) ) , } } // NOTE(gj): need to bomb out before rewriting shorthand rules to avoid emitting // correct-but-unhelpful errors, e.g., when there's an invalid `relations` declaration that // will result in a second error when rewriting a shorthand rule involving the relation // that would only distract from the _actual_ error (the invalid `relations` declaration). if diagnostics . iter ( ) . any ( Diagnostic :: is_unrecoverable ) { return diagnostics ; } // Rewrite shorthand rules in resource blocks before validating rule types. diagnostics . extend ( kb . rewrite_shorthand_rules ( ) . into_iter ( ) . map ( Into :: into ) ) ; // NOTE(gj): need to bomb out before rule type validation in case additional rule types // were defined later on in the file that encountered the unrecoverable error. Those // additional rule types might extend the valid shapes for a rule type defined in a // different, well-parsed file that also contains rules that don't conform to the shapes // laid out in the well-parsed file but *would have* conformed to the shapes laid out in // the file that failed to parse. if diagnostics . iter ( ) . any ( Diagnostic :: is_unrecoverable ) { return diagnostics ; } // Generate appropriate rule_type definitions using the types contained in policy resource // blocks. if let Err ( e ) = kb . create_resource_specific_rule_types ( ) { diagnostics . push ( e . into ( ) ) ; } // check rules are valid against rule types diagnostics . append ( & mut kb . validate_rules ( ) ) ; // Perform validation checks against the whole policy if ! self . ignore_no_allow_warning { if let Some ( w ) = check_no_allow_rule ( & kb ) { diagnostics . push ( w ) } } // Check for has_permission calls alongside resource block definitions if let Some ( w ) = check_resource_blocks_missing_has_permission ( & kb ) { diagnostics . push ( Diagnostic :: Warning ( w . into ( ) ) ) } ; diagnostics }
Load `sources` into the KB, returning compile-time diagnostics accumulated during the load.
Load ` sources ` into the KB returning compile - time diagnostics accumulated during the load .
&self
sources
Vec<Source>
&self
sources
Vec<Source>