diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..c0320e4 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index ea8c4bf..cb151c4 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +**/.DS_Store \ No newline at end of file diff --git a/LICENSE b/LICENSE index 1fb799d..67e2cf8 100644 --- a/LICENSE +++ b/LICENSE @@ -2,7 +2,8 @@ MIT License Copyright (c) 2023 McMaster Centre for Software Certification (McSCert) -Permission is hereby granted, free of charge, to any person obtaining a copy +Permission is + hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell diff --git a/examples/test.p4 b/examples/test.p4 index 53686a0..b0c4ed4 100644 --- a/examples/test.p4 +++ b/examples/test.p4 @@ -1,3 +1,4 @@ + // This P4 file contains only a preamble, it is not meant to be used on its own. #ifndef _COMMON_CONFIGP4 @@ -25,9 +26,6 @@ #endif #endif -#include "common/headers.p4" -#include "common/util.p4" - #ifdef TARGET_V1 struct mac_learn_digest { bit<48> src_addr; diff --git a/src/features/semantic_tokens.rs b/src/features/semantic_tokens.rs index a84fabe..4a39871 100644 --- a/src/features/semantic_tokens.rs +++ b/src/features/semantic_tokens.rs @@ -1,34 +1,168 @@ +use crate::metadata::{AstQuery, NodeKind, VisitNode, Visitable}; +use crate::metadata::{BaseType, Type}; +use std::sync::{Arc, Mutex}; use tower_lsp::lsp_types::{ SemanticToken, SemanticTokenType, SemanticTokens, SemanticTokensLegend, SemanticTokensResult, }; - +lazy_static::lazy_static! { + static ref TOKENS_TYPES: Vec = vec![ + SemanticTokenType::VARIABLE, + SemanticTokenType::STRING, + SemanticTokenType::KEYWORD, + SemanticTokenType::TYPE, + SemanticTokenType::NUMBER, + SemanticTokenType::FUNCTION, + SemanticTokenType::MODIFIER, + SemanticTokenType::DECORATOR, + ]; +} pub fn get_legend() -> SemanticTokensLegend { SemanticTokensLegend { - token_types: vec![SemanticTokenType::VARIABLE, SemanticTokenType::FUNCTION], + token_types: TOKENS_TYPES.clone(), token_modifiers: vec![], } } +pub struct ColorData { + line: u32, + start: u32, + length: u32, + node_type: u32, +} -pub fn get_tokens() -> SemanticTokensResult { - let tokens: Vec = vec![ - SemanticToken { - delta_line: 0, - delta_start: 0, - length: 5, - token_type: 0, - token_modifiers_bitset: 0, - }, - SemanticToken { - delta_line: 0, - delta_start: 5, - length: 5, - token_type: 1, +pub fn get_tokens(ast_query: &Arc>) -> SemanticTokensResult { + //Getting ast data + let ast_query = ast_query.lock().unwrap(); + let root_visit = ast_query.visit_root(); + let mut array = get_visit_nodes(root_visit); + //sort line + + array.sort_by_key(|token| token.line); + + let mut prev = 0; + let mut tokens: Vec = vec![]; + + let mut temp_array: Vec = Vec::new(); + for item in array { + //Calculating the line diff between current and previous line + let line = ((item.line - prev) as i32).abs(); + + prev = item.line; + //If line is greater than 0 then we save the temp array of tokens + if line > 0 && temp_array.len() > 0 { + let mut max_val = 0; + temp_array.sort_by_key(|&token| token.delta_start); //sorting the start pos + //setting the first deltaline to conatin the diff value (line) and setting all other to 0 + for i in 0..temp_array.len() { + if temp_array[i].delta_line > max_val { + max_val = temp_array[i].delta_line; + } + temp_array[i].delta_line = 0; + } + temp_array[0].delta_line = max_val; + + //ReCalculating the delta start relative to the previous start pos + let mut prev_start = 0; + temp_array = temp_array + .iter() + .map(|token| { + let temp_token = SemanticToken { + delta_line: token.delta_line, + delta_start: token.delta_start - prev_start.clone(), + length: token.length, + token_type: token.token_type, + token_modifiers_bitset: 0, + }; + + prev_start = token.delta_start; + return temp_token; + }) + .collect(); + + tokens.extend(temp_array); //concating two vectors + temp_array = Vec::new(); + } + + temp_array.push(SemanticToken { + delta_line: line as u32, + delta_start: item.start, + length: item.length, + token_type: item.node_type, token_modifiers_bitset: 0, - }, - ]; + }); + } SemanticTokensResult::Tokens(SemanticTokens { result_id: None, data: tokens, }) } + +pub fn get_visit_nodes(visit_node: VisitNode) -> Vec { + //Going throuhg all childrens + let childrens = visit_node.get_children(); + let mut array: Vec = Vec::new(); + for child in &childrens { + array.append(&mut get_visit_nodes(child.clone())); + } + + //Setting the node kidn with associated index from token type vector + let node_visit = visit_node.get(); + let kind = &node_visit.kind; + let temp_cmp = (TOKENS_TYPES.len() + 1) as u32; + let mut node_type: u32 = temp_cmp; + match kind { + NodeKind::Type(type_node_visit) => match type_node_visit { + Type::Base(base_types) => { + match base_types { + BaseType::String => { + node_type = 1; + } + _ => { + node_type = 4; + } + }; + } + Type::Name => { + node_type = 3; + } + Type::Specialized => { + node_type = 6; + } + _ => { + node_type = 7; + } + }, + NodeKind::Name => { + node_type = 0; + } + NodeKind::Direction(_dir_node) => { + node_type = 1; + } + NodeKind::KeyWord => { + node_type = 5; + } + NodeKind::Expression => { + node_type = 7; + } + NodeKind::ValueSymbol => { + node_type = 4; + } + _ => { + debug!("Error in Tokens {:?}", kind); + } + }; + //only pushing node types that we support currently + if node_type != temp_cmp { + let temp_length = ((node_visit.range.end.character - node_visit.range.start.character) + as i32) + .abs() as u32; + array.push(ColorData { + length: temp_length, + start: node_visit.range.start.character, + line: node_visit.range.start.line, + node_type: node_type, + }); + } + + return array; +} diff --git a/src/file.rs b/src/file.rs index 3ccd3bd..4363725 100644 --- a/src/file.rs +++ b/src/file.rs @@ -116,7 +116,7 @@ impl File { } pub fn get_semantic_tokens(&self) -> Option { - Some(semantic_tokens::get_tokens()) + Some(semantic_tokens::get_tokens(&self.ast_manager)) } pub fn get_definition_location(&self, position: Position) -> Option { diff --git a/src/metadata/mod.rs b/src/metadata/mod.rs index 74846c7..409ff12 100644 --- a/src/metadata/mod.rs +++ b/src/metadata/mod.rs @@ -9,3 +9,4 @@ pub use ast_manager::{AstEditor, AstManager, AstQuery}; pub use st_manager::{SymbolTableEdit, SymbolTableEditor, SymbolTableManager, SymbolTableQuery}; pub use symbol_table::Field; pub use symbol_table::{Symbol, SymbolTable, SymbolTableActions, Symbols}; +pub use types::{BaseType, Type};